web-dev-qa-db-fra.com

Comment effectuer la condition OR dans Django queryset?

Je veux écrire une requête Django équivalente à cette requête SQL:

SELECT * from user where income >= 5000 or income is NULL.

Comment construire le filtre Django queryset?

User.objects.filter(income__gte=5000, income=0)

Cela ne fonctionne pas, car il ANDs les filtres. Je veux OR les filtres pour obtenir l'union des ensembles de requêtes individuels.

252
Elisa
from Django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

via Documentation

489
Lakshman Prasad

Parce que les QuerySets implémentent l'opérateur Python __or__ (|), ou l'union, cela fonctionne. Comme on pouvait s'y attendre, l'opérateur binaire | renvoie un QuerySet afin que order_by(), .distinct() et que d'autres filtres de requête puissent être ajoutés à la fin.

combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')

Mise à jour 2019-06-20: Ceci est maintenant complètement documenté dans le référence de l'API QuerySet de Django 2.1 . Une discussion plus historique peut être trouvée dans ticket DjangoProject # 213 .

52
hobs

Les deux options sont déjà mentionnées dans les réponses existantes:

from Django.db.models import Q
q1 = User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

et

q2 = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)

Cependant, il semble y avoir une certaine confusion quant à la préférence.

Le fait est que ils sont identiques au niveau SQL , alors n'hésitez pas à choisir celui que vous préférez!

Le Django ORM Cookbook en parle en détail, voici la partie pertinente:


queryset = User.objects.filter(
        first_name__startswith='R'
    ) | User.objects.filter(
    last_name__startswith='D'
)

mène à

In [5]: str(queryset.query)
Out[5]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

et

qs = User.objects.filter(Q(first_name__startswith='R') | Q(last_name__startswith='D'))

mène à

In [9]: str(qs.query)
Out[9]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
 "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
  "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
  "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
  WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

source: Django-orm-cookbook


1
jojo