How to Chain Querysets in Django: Syntax and Examples
In Django, you can chain querysets using the
union() method to combine querysets of the same model or compatible fields. Alternatively, use Python's itertools.chain() to concatenate querysets from different models, but note this returns an iterable, not a queryset.Syntax
There are two main ways to chain querysets in Django:
- Using
union(): Combines querysets of the same model or compatible fields into a single queryset. - Using
itertools.chain(): Concatenates querysets from different models or incompatible fields into a single iterable.
union() returns a queryset, so you can continue filtering or ordering. itertools.chain() returns an iterable, so it does not support queryset methods.
python
qs1 = Model.objects.filter(condition1) qs2 = Model.objects.filter(condition2) # Using union combined_qs = qs1.union(qs2) # Using itertools.chain from itertools import chain combined_iterable = chain(qs1, qs2)
Example
This example shows how to chain two querysets of the same model using union() and how to chain querysets of different models using itertools.chain().
python
from django.db import models from itertools import chain class Book(models.Model): title = models.CharField(max_length=100) class Author(models.Model): name = models.CharField(max_length=100) # Querysets of the same model books1 = Book.objects.filter(title__startswith='A') books2 = Book.objects.filter(title__startswith='B') combined_books = books1.union(books2) print('Books starting with A or B:') for book in combined_books: print(book.title) # Querysets of different models authors = Author.objects.filter(name__startswith='A') combined_iterable = chain(books1, authors) print('\nCombined books and authors:') for item in combined_iterable: if isinstance(item, Book): print(f'Book: {item.title}') else: print(f'Author: {item.name}')
Output
Books starting with A or B:
A Tale of Two Cities
Brave New World
Combined books and authors:
Book: A Tale of Two Cities
Book: Another Book
Author: Alice
Author: Alan
Common Pitfalls
1. Using union() with querysets of different models or incompatible fields causes errors.
Only querysets of the same model or with matching fields can be combined with union().
2. itertools.chain() returns an iterable, not a queryset. You cannot use queryset methods like filter() or order_by() on the result.
3. union() removes duplicates by default. Use all=True to include duplicates if needed.
python
# Wrong: union of different models # qs1 = Book.objects.all() # qs2 = Author.objects.all() # combined = qs1.union(qs2) # Raises error # Right: use itertools.chain for different models from itertools import chain combined = chain(qs1, qs2)
Quick Reference
| Method | Use Case | Returns | Notes |
|---|---|---|---|
| union() | Combine querysets of same model or compatible fields | QuerySet | Removes duplicates by default; supports further queryset methods |
| itertools.chain() | Combine querysets of different models or incompatible fields | Iterable | Does not support queryset methods; manual iteration only |
Key Takeaways
Use
union() to chain querysets of the same model or with matching fields for a combined queryset.Use
itertools.chain() to combine querysets from different models but remember it returns an iterable, not a queryset.union() removes duplicates by default; pass all=True to keep duplicates.You cannot chain querysets of different models using
union() without errors.Chained querysets with
union() support further filtering and ordering.