Question

If I have a parent model and a child model, how can I then list all child objects of a parent object, and have a filtered count for each child object, when listing them?

To give an example, assume we have these models:

class Category(models.Model):
    ...

class SubCategory(models.Model):
    category = models.ForeignKey(Category)
    ....

class Tag(models.Model):
    ....

class Article(models.Model)
    sub_category = models.ForeignKey(SubCategory)
    tag = models.ForeignKey(Tag)

Then we have a DetailView for a Category, in which all SubCatoegories for that Category are listed. In this list, we want to have a count on each SubCategory entry, on the number of articles it contains that also is of a certain tag (that is, not a count on all articles of that SubCategory, which seems much more trivial to build). Something like this:

{% for sub_category in category.sub_category_set.all %}
    {{ sub_category.name }} -- {{ sub_category.articles_set.filter(tag='xyz').all|length }}

I guess this has to be done in the views.py and/or models.py in some way in the end. I just wrote it like this to clarify what I mean. So, how can I achieve something like this?

Was it helpful?

Solution

You're right that you'll have to do this in the view. You can use annotation to get the number of filtered articles for each subcategory:

from django.db.models import Count

def my_view(request, other, arguments):
    ...
    subcategories = category.sub_category_set.filter(tag__tagname='xyz') \ 
                            .annotate(num_articles=Count('article__id'))
    ...

Pass subcategories to your template context, and in your template you can do this:

{% for subcategory in subcategories %}
    {{ subcategory.name }} -- {{ subcategory.num_articles }}
{% endfor %}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top