Q-объекты позволяют строить сложные условия с OR, AND, NOT.
Проблема без Q
# Обычный filter — только AND
Task.objects.filter(status='todo', priority=3)
# WHERE status='todo' AND priority=3
# Нельзя напрямую:
Task.objects.filter(status='todo' OR priority=3) # SyntaxError!
Базовое использование
from django.db.models import Q
# OR
Task.objects.filter(Q(status='todo') | Q(status='in_progress'))
# AND (то же что обычный filter)
Task.objects.filter(Q(status='todo') & Q(priority__gte=3))
# NOT
Task.objects.filter(~Q(status='done'))
Сложные комбинации
# (статус todo ИЛИ in_progress) И (приоритет высокий ИЛИ срок просрочен)
Task.objects.filter(
(Q(status='todo') | Q(status='in_progress')) &
(Q(priority=3) | Q(due_date__lt=today))
)
Динамическое построение фильтра
def search_tasks(query=None, status=None, user=None):
q = Q()
if query:
q &= Q(title__icontains=query) | Q(description__icontains=query)
if status:
q &= Q(status=status)
if user:
q &= Q(owner=user)
return Task.objects.filter(q)
В annotate
from django.db.models import Count, Q
Project.objects.annotate(
done_count=Count('tasks', filter=Q(tasks__status='done')),
todo_count=Count('tasks', filter=Q(tasks__status='todo')),
)
Сравнение двух полей
# Задачи где updated_at > created_at (т.е. обновлялись)
from django.db.models import F
Task.objects.filter(updated_at__gt=F('created_at'))
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!