Home > Enterprise >  How to count and filter object in Django template?
How to count and filter object in Django template?

Time:07-16

I have two models: in one, the user creates a post, and in the other, the likes of those posts are collected. Now I would like the number of these likes to be displayed on the post. Is there any way for all posts with the number of likes to be displayed on one template?

template.html:

<div >
        <ul >
    {%for post in posts %}
    
      <a id="like_{{post.id}}" href="" >
         {% for every_like in likes_obj%}{%if every_like.liked_what == post%}{{every_like.count}}{%endif%}{%endfor%}

## At this point I would like to see the number of likes for each post it is assigned to, but unfortunately {{every_like.count}} returns
 nothing.

      </a>
    
    {% endfor %}
        </ul>
    </div>

views.py:

def index(request):
    list = Post.objects.all().order_by('-date')

    paginator = Paginator(list, 10)

    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, "network/index.html", {
        "post_form": PostForm(),
        "posts": page_obj,
        "likes_obj": Like.objects.all()
    })

models.py:

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    subject = models.CharField(max_length=200, blank=False)
    content = models.TextField(blank=False)

class Like(models.Model):
    author_of_like = models.ForeignKey(User, on_delete=models.CASCADE)
    liked_what = models.ForeignKey(Post, on_delete=models.CASCADE)

CodePudding user response:

You can .annotate(…) [Django-doc] with:

from django.db.models import Sum

def index(request):
    posts = Post.objects.annotate(
        number_of_likes=Count('like')
    ).order_by('-date')

    paginator = Paginator(posts, 10)

    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, 'network/index.html', {
        'post_form': PostForm(),
        'posts': page_obj
    })

The Post objects that arise from this QuerySet will have an extra attribute .number_of_likes, so you render this with:

{%for post in posts.qs %}
    <a id="like_{{post.id}}" href="" > {{ post.number_of_likes }}</a>
{% endfor %}

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Note: Please do not name a variable list, it overrides the reference to the list builtin function [Python-doc]. Use for example posts.


Note: Section 9 of the HTTP protocol specifies that requests like GET and HEAD should not have side-effects, so you should not change entities with a simple link (with <a href="…">…</a> tags). Normally POST, PUT, PATCH, and DELETE requests are used for this. In that case you make a small <form> that will trigger a POST request, or you use some AJAX calls.

  • Related