Reputation: 2773
So, provided code like this:
class Category(models.Model):
parent = models.ForeignKey('self', null=True, blank=True)
name = models.CharField('name', max_length)
I might have a relationship like this: category_two's parent is category_one and category_three's parent is category two.
I want to filter out all the category that doesn't have children. this means like this:
category_three.category_set.count() == 0; # category_three has no children
category_two.category_set.count() != 0; # category_three's parent is category_two
But When I try this:
Category.objects.filter(category_set__count=0) # this is the wrong code that won't work
# this would actually gives out the following error message
#Cannot resolve keyword 'category_set' into field. Choices are: category, id, name, parent, parent_id
Basically what I want is filter out all the ending category, means the category that won't have any child.
Hope that I explained clearly. Any idea how to do this?
Upvotes: 2
Views: 1745
Reputation: 53659
Use the __isnull
lookup:
categories = Category.objects.filter(category__isnull=True)
In the context of a relationship, __isnull=True
matches if there are no related objects, and __isnull=False
matches if there is at least one related object. Alternatively, you can replace category__isnull=True
with category=None
, this will generate the same query.
Upvotes: 2
Reputation: 664
Try filtering on an annotation:
from django.db.models import Count
categories = Category.objects.annotate(num_children=Count('category_set')).filter(num_children__gt=0)
Annotating every category with a field of 'num_children' which is the count of the 'category_set' field and then filtering should get you only the categories that have children.
Upvotes: 3