Est-il possible de spécifier le type d'enregistrements dans Django QuerySet avec des indicateurs de type Python? Quelque chose comme QuerySet[SomeModel]
?
Par exemple, nous avons le modèle:
class SomeModel(models.Model):
smth = models.IntegerField()
Et nous voulons transmettre QuerySet de ce modèle en tant que paramètre in func:
def somefunc(rows: QuerySet):
pass
Mais comment spécifier le type d’enregistrements dans QuerySet, comme avec List[SomeModel]
:
def somefunc(rows: List[SomeModel]):
pass
mais avec QuerySet?
Une solution peut utiliser la classe de frappe Union.
from typing import Union, List
from Django.db.models import QuerySet
from my_app.models import MyModel
def somefunc(row: Union[QuerySet, List[MyModel]]):
pass
Désormais, lorsque vous coupez l'argument row
, il sait que le type renvoyé est une autre liste de MyModel ou une instance de MyModel, tout en indiquant que les méthodes de la classe QuerySet
sont également disponibles sur l'argument row
.
Je cherche une solution à cela aussi. La liste Django Developers contient un thread dans lequel ils discutent de la manière de mettre en œuvre une telle fonctionnalité.
Ils développent actuellement une extension Django à mypy , mais il semble que nous ayons peut-être de la chance pour notre demande spécifique. Dans leur feuille de route sous le titre "Probablement jamais":
Les ensembles de requêtes peuvent avoir un support partiel, mais des arguments complexes (comme Ceux pour les requêtes de filtrage et d'obtention de requêtes) ou les objets Q et F vont au-delà de. possibilités expressives de mypy comme il est maintenant.
En déclarant cela, nous devrons simplement utiliser la règle QuerySet
jusqu'à ce que les conditions s'améliorent.
J'ai créé cette classe d'assistance pour obtenir un indice de type générique:
from Django.db.models import QuerySet
from typing import Iterator, Union, TypeVar, Generic
T = TypeVar("T")
class ModelType(Generic[T]):
def __iter__(self) -> Iterator[Union[T, QuerySet]]:
pass
Ensuite, utilisez-le comme ceci:
def somefunc(row: ModelType[SomeModel]):
pass
Cela réduit le bruit chaque fois que j'utilise ce type et le rend utilisable entre les modèles (comme ModelType[DifferentModel]
).