142 votes

Comment utiliser les indicateurs de type Python avec Django QuerySet?

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?

78voto

A. J. Parr Points 2897

Une solution peut être d'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 couperez l'argument row , il saura que le type renvoyé est soit une autre liste de MyModel, soit une instance de MyModel, tout en laissant également entendre que les méthodes de la classe QuerySet sont disponibles. sur l'argument row aussi.

26voto

Or Duan Points 5708

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 modèles (comme ModelType[DifferentModel] ).

1voto

Bobort Points 526

Je suis à la recherche d'une solution à cela aussi. Les Développeurs Django liste a un thread dans lequel ils sont à discuter des moyens à mettre en œuvre une telle fonctionnalité.

Ils sont actuellement à l'élaboration d'un Django d'extension de mypy, mais il semble que nous peut-être pas de chance pour notre demande spécifique. Dans leur feuille de route, sous le titre de "Probablement Jamais":

Querysets peut avoir une certaine prise en charge partielle, mais des arguments complexes (comme les questions pour filtre et les requêtes get) ou Q et F les objets sont au-delà de la possibilités expressives de la mypy comme il est maintenant.

Indiquant que, nous allons juste utiliser de la plaine ole QuerySet jusqu'à ce que les conditions s'améliorent.

-12voto

ALJ Points 7

Si vous voulez passer un param, faites ceci:

 def somefunc(smth):
    pass
 

si vous voulez renvoyer un type de liste, utilisez la fonction list() .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X