This tip is particularly useful when you want to merge two or more querysets into a single queryset without losing
the capabilities of performing filter
, count
, distinct
, etc. operations.
Consider the following models:
class Story(models.Model):
title = models.CharField(max_length=255)
content = models.TextField(blank=True)
category = models.ForeignKey(Category, related_name='stories')
author = models.ForeignKey(User, related_name='stories')
class Medium(models.Model):
name = models.CharField(max_length=30, unique=True)
stories = models.ManyToManyField(Story)
Let’s say you want to display all the stories published in a specific Medium
together with stories written by a
User
using the Category
django. Note that this User
might have published stories in different Medium
:
medium = Medium.objects.get(name='Django Blog')
user = User.objects.get(username='vitor')
django_stories = medium.stories.all()
vitor_stories = user.stories.filter(category__name='django')
At this point we have two different querysets, one containing all the stories from a medium and other containing all the stories from a user using the django category.
The querysets can be merged like in the example below, using the |
operator:
stories = django_stories | vitor_stories # merge querysets
And you still can perform queryset operations:
recent_stories = stories.distinct().order_by('-date')[:10]
It’s important to note that the merge/combine operator |
only works on querysets from the same model and before the
slicing it.