Ответ 1
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))
Я хочу написать запрос Django, эквивалентный этому запросу SQL:
SELECT * from user where income >= 5000 or income is NULL.
Как построить фильтр наборов запросов Django?
User.objects.filter(income__gte=5000, income=0)
Это не работает, потому что это AND
фильтры. Я хочу OR
фильтры, чтобы получить объединение отдельных наборов запросов.
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))
Поскольку QuerySets реализует оператор Python __or__
(|
) или объединение, он просто работает. Как и следовало ожидать, |
Двоичный оператор возвращает QuerySet
так что order_by()
, .distinct()
и другие фильтры .distinct()
могут быть добавлены до конца.
combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')
Обновление 2019-06-20: теперь это полностью документировано в справочнике по API QuerySet Django 2.1. Более историческое обсуждение можно найти в билете DjangoProject # 21333.
Оба варианта уже упомянуты в существующих ответах:
from django.db.models import Q
q1 = User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))
и
q2 = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
Однако, похоже, существует некоторая путаница в отношении того, какой из них предпочтительнее.
Дело в том, что они идентичны на уровне SQL, поэтому не стесняйтесь выбирать, что вам нравится!
Поваренная книга Django ORM рассказывает об этом более подробно, вот соответствующая часть:
queryset = User.objects.filter(
first_name__startswith='R'
) | User.objects.filter(
last_name__startswith='D'
)
ведет к
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%)'
и
qs = User.objects.filter(Q(first_name__startswith='R') | Q(last_name__startswith='D'))
ведет к
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%)'
источник: django-orm-cookbook