How to combine multiple QuerySets in Django?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Combining QuerySets in Django can mean several different things: applying an OR filter to one model, uniting two QuerySets that return compatible rows, or chaining already-evaluated results in Python. The right approach depends on whether the combination should happen in SQL or in Python after the data has been fetched.
For most same-model filtering tasks, the best answer is to keep the work in the database using Q objects or compatible QuerySet operators. Python-level combination is usually the fallback, not the default.
Combine Conditions With Q
If you are really combining criteria on the same model, Q objects are often the cleanest approach.
This produces one SQL query with an OR condition. It is usually better than building multiple QuerySets and combining them later.
Use the | Operator for Compatible QuerySets
Django also allows combining compatible QuerySets of the same model with |.
This is convenient, but conceptually it is still about building a database-level union of compatible conditions on the same model.
If what you really want is “author is A or B,” a single filter with Q is often clearer.
Use union() for Compatible Result Sets
If you need SQL set union behavior, Django provides union().
This works best when the selected columns are compatible across the participating QuerySets.
It is a stronger SQL-style operation than simply expressing OR logic.
Chain Results in Python When the Models Differ
If the QuerySets come from different models, database-level combination is usually not possible in the same direct way. In that case, you may need to combine the results in Python.
This is fine when you truly need heterogeneous objects, but note that this is no longer a lazy database QuerySet in the Django sense. Once you chain and list the results, you are working with Python objects in memory.
Preserve Laziness When You Can
One of Django QuerySet’s strengths is lazy evaluation. If you convert everything to a list too early, you lose:
- database-level optimization
- lazy slicing
- later filtering or ordering in SQL
That is why you should keep the combination in the ORM when possible and drop to Python only when the data model actually requires it.
Ordering and Distinct Behavior
When combining QuerySets, pay attention to ordering and duplicates.
For example, an OR condition may naturally include rows that satisfy both sides. Depending on the operation, you may need distinct().
Whether this is necessary depends on the joins and filters involved.
Common Pitfalls
A common mistake is using Python-level chain when the combination could have been done in SQL more efficiently.
Another mistake is trying to combine QuerySets from different models as if Django could always treat them as one queryable object. Usually it cannot.
Developers also sometimes use the | operator without asking whether a single Q(...) expression would be clearer.
Finally, once you materialize results into a list, you no longer have a real QuerySet with lazy ORM behavior. That tradeoff should be intentional.
Summary
- Use
Qobjects when the real need is one query with combined conditions. - Use
|for compatible same-model QuerySets when that syntax is clearer. - Use
union()for SQL set-union style combinations of compatible result sets. - Use Python-level
chainonly when database-level combination is not the right model. - Prefer keeping the work in the database until you have a reason not to.
Related reading
- How to completely clear down, reset and restart a Cassandra cluster?
- How to compute a 3D Morton number interleave the bits of 3 ints
- How to configure access permissions for Cassandra on Linux Ubuntu
- how to configure redis ttl with spring boot 2.0
- How to combine python asyncio with threads?
- How to comment out a block of code in Python
- How to configure spring-boot to use file based H2 database
- How to configure spring-data-mongodb to use a replica set via properties

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.