Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter queryset by reverse exists check in Django

Tags:

python

django

I have models:

class Post(models.Model):
    content = models.CharField()
    user = models.ForeignKey('users.User')
    active = models.BooleanField(default=True)

class Comment(models.Model):
    post = models.ForeignKey(Post, related_name='post_comments')

And a queryset which is filtered by query params:

user = request.QUERY_PARAMS.get('user_id', None)
active = request.QUERY_PARAMS.get('active', None)
has_comments = request.QUERY_PARAMS.get('has_comments', None)

qs = Post.objects.all()

if user:
    qs = qs.filter(user=user)
if active:
    qs = qs.filter(active=active)
if has_comments:
    ???

I don't get how I can filter this query while maintaining all the previous filters. Is it possible?

like image 676
Mark Avatar asked Jun 03 '15 22:06

Mark


1 Answers

According to the documentation:

To refer to a “reverse” relationship, just use the lowercase name of the model.

From this answer it follows your code would be:

if user:
    qs = qs.filter(user=user)
if active:
    qs = qs.filter(active=active)
if has_comments:
    qs = qs.filter(comment__isnull=False)

With regards to performance take this answer into account:

Django doesn't support the select_related() method for reverse foreign key lookups, so the best you can do without leaving Python is two database queries.

You should also have a look at prefetch_related which can, unlike select_related do lookups across reverse ForeignKeys, albeit with a separate query for each element of the queryset.

like image 165
Sebastian Wozny Avatar answered Oct 02 '22 22:10

Sebastian Wozny