PacktPublishing / Django-5-By-Example

Django 5 By Example (5th Edition) published by Packt
https://djangobyexample.com/
MIT License
244 stars 106 forks source link

Chapter 3 - Page 127 - Creating a template tag that returns a QuerySet #26

Open seyyed-amirreza-hosseini opened 3 months ago

seyyed-amirreza-hosseini commented 3 months ago
from django.db.models import Count

@register.simple_tag
def get_most_commented_posts(count=5):
   return Post.published.annotate(
     total_comments=Count('comments')
   ).order_by('-total_comments')[:count]

this approach has 2 problems:

  1. the query set will return all published posts with the most comments. However, the problem is that it counts inactive comments (active=False) as well. It should not do that because we might have a comment with inappropriate content and we don't want to count that as a comment to show to the users.

  2. the second issue is that we don't have to display posts with no comments. but the query set above will show posts with no comments too.

here is my solution:

@register.simple_tag
def get_most_commented_posts(count=5):
    posts = Post.published.filter(comments__active=True).annotate(
        total_comments=Count('comments')
    ).order_by('-total_comments')[:count]

    return posts

This function retrieves most commented posts, where the comments are active.