Saturnix
Saturnix

Reputation: 10564

Correct way to count for a foreign key model in Django template

class Author(models.Model):
    name = models.CharField()

class Article(models.Model):
    author = models.ForeignKey(Author)

let's suppose I need to show in a template how many Articles are from a determinate author. This is the view:

def myview(request):
    context = {
        'authors': Author.objects.all()
    }

simply doing {{ author.Articles||length }} would require me to edit the Author model. If this is the correct way (it obviously isn't), should I do this at the models.py level or in the view myview?

I believe that editing the model in models.py would result in a really bad code design.

Doing so in myview would require me to do something like this:

authors = []
for author in authors:
    count = Article.objects.filter(author__exact=author).count()
    authors.append(author, count)
    horrendously_bad_code_design_context = {
        'authors': authors,
    }

What is the correct way to do so? I believe that both these implementations are really bad and 'hacky'.

Upvotes: 2

Views: 1198

Answers (1)

Ivan
Ivan

Reputation: 6013

If you already have a retrieved author and you want to get the article count then using the related manager's count method (author.article_set.count()) is probably okay.

On the other hand if you are iterating over an (possibly lagre) Author queryset just to get the counts, it will do a lot of queries (one to retrieve all authors and one per author to get the count). This can be easily replaced by an annotated queryset that will result in only one query:

from django.db.models import Count

Author.objects.annotate(article_count=Count('articles'))

Later on in your in your template you can just use {{ author.article_count }}.

Upvotes: 3

Related Questions