Q objects allow you to build complex query conditions using OR, AND, and NOT.
The Problem Without Q
# Regular filter — AND only
Task.objects.filter(status='todo', priority=3)
# WHERE status='todo' AND priority=3
# This is not possible directly:
Task.objects.filter(status='todo' OR priority=3) # SyntaxError!
Basic Usage
from django.db.models import Q
# OR
Task.objects.filter(Q(status='todo') | Q(status='in_progress'))
# AND (same as a regular filter)
Task.objects.filter(Q(status='todo') & Q(priority__gte=3))
# NOT
Task.objects.filter(~Q(status='done'))
Complex Combinations
# (status is todo OR in_progress) AND (priority is high OR deadline is past)
Task.objects.filter(
(Q(status='todo') | Q(status='in_progress')) &
(Q(priority=3) | Q(due_date__lt=today))
)
Dynamic Filter Building
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)
In 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')),
)
Comparing Two Fields
# Tasks where updated_at > created_at (i.e. they have been modified)
from django.db.models import F
Task.objects.filter(updated_at__gt=F('created_at'))
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!