A little Django app allows for compound querysets between different tables. Especially useful for pagination of said results.
Django versions supported: 1.8, 1.9, 1.10
Python versions supported: 2.7, 3.3, 3.4, 3.5
You can obtain the source code for django-compoundqueryset
from here:
https://github.com/brianwawok/django-compoundqueryset
Using pip:
pip install django-compoundqueryset
Sometimes you might want to combine two different tables with similar fields and show them to users. For example:
from django.db import models
class FirstModel(models.Model):
age = models.IntegerField()
name = models.TextField(max_length=100)
color = models.TextField(max_length=100)
class SecondModel(models.Model):
age = models.IntegerField()
name = models.TextField(max_length=100)
size = models.IntegerField()
And you want to paginate across them
from django.core.paginator import Paginator
from djcompoundqueryset import CompoundQueryset
qs_1 = FirstModel.objects.order_by('age').all()
qs_2 = SecondModel.objects.order_by('age').all()
combined_queryset = qs_1 | qs_2
p = Paginator(combined_queryset, 10)
You will get the dreaded error
Merging 'QuerySet' classes must involve the same values in each case.
Now with django-compoundqueryset, you can do:
from django.core.paginator import Paginator
from djcompoundqueryset import CompoundQueryset
qs_1 = FirstModel.objects.order_by('age').all()
qs_2 = SecondModel.objects.order_by('age').all()
combined_queryset = CompoundQueryset(qs_1, qs_2, max_items=100)
p = Paginator(combined_queryset, 10)
You can now iterate over these models in a view, showing the age. Max_items says you will never use more than that many items, so limit the count a queries. Useful if you have capped pagination.
The goal is to beat the naive implementation (load all records into memory and deal with there), but we may not beat a RawSQL union all monster. If performance is really important you may need to do that.
If used in a Django Paginator, we will normally do 1 count(*) query per queryset, and then only load the required records.