Posted on October 1, 2008 at 8:20 pm

Merging Django querysets

This one’s pretty basic (from the docs) , but I end up using it all the times. Being able to “AND” and “OR” django querysets can really simplify a lot of code. Here’s an instance (a simplification of the setup I have in tagz). Lets start by defining 2 models.

from django.db import models

class Tag( models.Model ) :
    text = models.CharField(max_length=255)

class Post( models.Model ) :
    link  = models.URLField(max_length=2048)
    title = models.CharField(max_length=255)
    tags  = models.ManyToManyField(Tag)

Now, lets say I want to get all Posts tagged as django or python.

qs = Post.objects.filter(tags__text='python') | Post.objects.filter(tags__text='django')

Now as intuitive as it might seem, using AND doesn’t seem to work.

qs = Post.objects.filter(tags__text='python') & Post.objects.filter(tags__text='django')
# qs.count() returns 0

So, we end up chaining filters like this:

qs = Post.objects.filter(tags__text='python').filter(tags__text='django')

Which boils down to simple for loop.

def filter_tags( tags ) :
    '''
    tags: a list of strings
    '''
    p = Post.objects.all()
    for t in tags :
        p = p.filter(tags__text=t)
    return p

Tags:

4 Responses to “Merging Django querysets”

  1. David Christiansen on October 2nd, 2008 at 11:49 AM says:

    Why not define a custom manager instead of the filter_tags function?

  2. admin on October 2nd, 2008 at 1:10 PM says:

    @David: It certainly should be. But the function was just supposed to be an example, I was too lazy to type a couple of extra lines for a class definition :)

  3. frits on October 10th, 2008 at 6:20 PM says:

    Wouldn’t it be possible to make a set of the required tags first, and then use the filter(tags__in=tag_set) to get only those items tagged with the tags in the tag_set?

  4. Merging Django querysets – redux | Jeethu's Blog on November 7th, 2008 at 5:35 AM says:

    [...] my previous post on with the same title, frits commented asking wouldn’t it be possible to use [...]

Leave a Reply