python / expert
Snippet
Django Q Objects for Complex Database Queries
Django Q objects enable complex OR/AND database queries that cannot be achieved with simple filter() calls. This example demonstrates building dynamic search queries with multiple optional filters, combining lookups with bitwise operators, and using conditional annotations to calculate discounted prices. The related products query showcases advanced matching with annotation and random ordering.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from django.db.models import Q, Count, F, Case, When, IntegerFieldfrom django.db.models.functions import Concatfrom.models import Product, Categoryclass ProductManager(models.Manager):def search_products(self, query, category=None, min_price=None, max_price=None, in_stock=None, is_featured=None):"""Complex product search with multiple filter conditions."""queryset = self.get_queryset()search_query = Q(name__icontains=query) | \Q(description__icontains=query) | \Q(sku__iexact=query)if category:search_query &= Q(category__slug=category)price_query = Q()if min_price is not None:price_query &= Q(price__gte=min_price)if max_price is not None:price_query &= Q(price__lte=max_price)stock_query = Q()if in_stock is True:stock_query = Q(stock_quantity__gt=0)elif in_stock is False:stock_query = Q(stock_quantity=0)featured_query = Q(is_featured=True) if is_featured else Q()combined_query = search_query & price_query & stock_query & featured_queryreturn queryset.filter(combined_query).select_related('category').annotate(category_product_count=Count('category__products'),discounted_price=Case(When(discount__gt=0, then=F('price') * (1 - F('discount') / 100)),default=F('price'),output_field=IntegerField())).order_by('-is_featured', '-created_at')def get_related_products(self, product, limit=5):"""Find related products using category and tag matching."""return self.get_queryset().filter(Q(category=product.category) | Q(tags__in=product.tags.all()),Q(is_active=True) & ~Q(pk=product.pk)).annotate(matching_criteria=Count('category') + Count('tags')).order_by('-matching_criteria', '?')[:limit]
django
Breakdown
1
from django.db.models import Q, Count, F, Case, When, IntegerField
Import Q objects and aggregation/conditional helpers
2
search_query = Q(name__icontains=query) | Q(description__icontains=query)
Create OR query using pipe operator with case-insensitive contains
3
if category: search_query &= Q(category__slug=category)
Add AND condition to existing query using &= operator
4
price_query = Q() if min_price is None and max_price is None else Q(price__gte=min_price) & Q(price__lte=max_price)
Build price range query conditionally
5
combined_query = search_query & price_query & stock_query & featured_query
Combine all query components with AND logic
6
discounted_price=Case(When(discount__gt=0, then=F('price') * (1 - F('discount') / 100)), default=F('price'))
Use Case/When for conditional annotation calculation
7
matching_criteria=Count('category') + Count('tags')
Annotate with count of matching criteria for ranking
8
order_by('-matching_criteria', '?')
Order by relevance then randomize within same rank