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
David Christiansen on October 2nd, 2008 at 11:49 AM says:
Why not define a custom manager instead of the filter_tags function?
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
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?
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 [...]