Filtering another model field count for each item from object_list (List View, Django)












1















I am learining Django trying to create a blog. I have a ListView of Post model on Homepage. I am trying to add new context data (number of comments from separate model Comment for each item from ListView). However I wasn't able to correctly filter number of Comments for each Post by using __in (it just shows same total number of Comments on each Post item of ListView). Could you please help me with how to get a correct filter to show for each ListView Post item how many Comments does it have?



Thanks!



Post Model:



class Post(models.Model):
class Meta:
verbose_name = 'запись'
verbose_name_plural = 'записи'

title = models.CharField('название', max_length=300, help_text='Не более 300 знаков')
content = models.TextField('текст записи')
date_posted = models.DateTimeField('дата публикации', default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='автор')

def __str__(self):
return self.title

def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})


Comment model:



class Comment(models.Model):
class Meta:
verbose_name = 'комментарий'
verbose_name_plural = 'комментарии'

content = models.CharField('текст комментария', max_length=500, help_text='Не более 500 знаков')
date_posted = models.DateTimeField('дата публикации', default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name = 'автор')
postid = models.ForeignKey(Post, on_delete=models.CASCADE)


ListView in views.py:



class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comments'] = Comment.objects.filter(postid__in = self.object_list)
return context


Context data that I use in html template:



{% for post in posts%}
{{ post.content }}
{{ comments.count }}
{% endfor %}









share|improve this question



























    1















    I am learining Django trying to create a blog. I have a ListView of Post model on Homepage. I am trying to add new context data (number of comments from separate model Comment for each item from ListView). However I wasn't able to correctly filter number of Comments for each Post by using __in (it just shows same total number of Comments on each Post item of ListView). Could you please help me with how to get a correct filter to show for each ListView Post item how many Comments does it have?



    Thanks!



    Post Model:



    class Post(models.Model):
    class Meta:
    verbose_name = 'запись'
    verbose_name_plural = 'записи'

    title = models.CharField('название', max_length=300, help_text='Не более 300 знаков')
    content = models.TextField('текст записи')
    date_posted = models.DateTimeField('дата публикации', default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='автор')

    def __str__(self):
    return self.title

    def get_absolute_url(self):
    return reverse('post-detail', kwargs={'pk': self.pk})


    Comment model:



    class Comment(models.Model):
    class Meta:
    verbose_name = 'комментарий'
    verbose_name_plural = 'комментарии'

    content = models.CharField('текст комментария', max_length=500, help_text='Не более 500 знаков')
    date_posted = models.DateTimeField('дата публикации', default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name = 'автор')
    postid = models.ForeignKey(Post, on_delete=models.CASCADE)


    ListView in views.py:



    class PostListView(ListView):
    model = Post
    template_name = 'blog/home.html'
    context_object_name = 'posts'
    ordering = ['-date_posted']
    paginate_by = 5

    def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['comments'] = Comment.objects.filter(postid__in = self.object_list)
    return context


    Context data that I use in html template:



    {% for post in posts%}
    {{ post.content }}
    {{ comments.count }}
    {% endfor %}









    share|improve this question

























      1












      1








      1








      I am learining Django trying to create a blog. I have a ListView of Post model on Homepage. I am trying to add new context data (number of comments from separate model Comment for each item from ListView). However I wasn't able to correctly filter number of Comments for each Post by using __in (it just shows same total number of Comments on each Post item of ListView). Could you please help me with how to get a correct filter to show for each ListView Post item how many Comments does it have?



      Thanks!



      Post Model:



      class Post(models.Model):
      class Meta:
      verbose_name = 'запись'
      verbose_name_plural = 'записи'

      title = models.CharField('название', max_length=300, help_text='Не более 300 знаков')
      content = models.TextField('текст записи')
      date_posted = models.DateTimeField('дата публикации', default=timezone.now)
      author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='автор')

      def __str__(self):
      return self.title

      def get_absolute_url(self):
      return reverse('post-detail', kwargs={'pk': self.pk})


      Comment model:



      class Comment(models.Model):
      class Meta:
      verbose_name = 'комментарий'
      verbose_name_plural = 'комментарии'

      content = models.CharField('текст комментария', max_length=500, help_text='Не более 500 знаков')
      date_posted = models.DateTimeField('дата публикации', default=timezone.now)
      author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name = 'автор')
      postid = models.ForeignKey(Post, on_delete=models.CASCADE)


      ListView in views.py:



      class PostListView(ListView):
      model = Post
      template_name = 'blog/home.html'
      context_object_name = 'posts'
      ordering = ['-date_posted']
      paginate_by = 5

      def get_context_data(self, **kwargs):
      context = super().get_context_data(**kwargs)
      context['comments'] = Comment.objects.filter(postid__in = self.object_list)
      return context


      Context data that I use in html template:



      {% for post in posts%}
      {{ post.content }}
      {{ comments.count }}
      {% endfor %}









      share|improve this question














      I am learining Django trying to create a blog. I have a ListView of Post model on Homepage. I am trying to add new context data (number of comments from separate model Comment for each item from ListView). However I wasn't able to correctly filter number of Comments for each Post by using __in (it just shows same total number of Comments on each Post item of ListView). Could you please help me with how to get a correct filter to show for each ListView Post item how many Comments does it have?



      Thanks!



      Post Model:



      class Post(models.Model):
      class Meta:
      verbose_name = 'запись'
      verbose_name_plural = 'записи'

      title = models.CharField('название', max_length=300, help_text='Не более 300 знаков')
      content = models.TextField('текст записи')
      date_posted = models.DateTimeField('дата публикации', default=timezone.now)
      author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='автор')

      def __str__(self):
      return self.title

      def get_absolute_url(self):
      return reverse('post-detail', kwargs={'pk': self.pk})


      Comment model:



      class Comment(models.Model):
      class Meta:
      verbose_name = 'комментарий'
      verbose_name_plural = 'комментарии'

      content = models.CharField('текст комментария', max_length=500, help_text='Не более 500 знаков')
      date_posted = models.DateTimeField('дата публикации', default=timezone.now)
      author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name = 'автор')
      postid = models.ForeignKey(Post, on_delete=models.CASCADE)


      ListView in views.py:



      class PostListView(ListView):
      model = Post
      template_name = 'blog/home.html'
      context_object_name = 'posts'
      ordering = ['-date_posted']
      paginate_by = 5

      def get_context_data(self, **kwargs):
      context = super().get_context_data(**kwargs)
      context['comments'] = Comment.objects.filter(postid__in = self.object_list)
      return context


      Context data that I use in html template:



      {% for post in posts%}
      {{ post.content }}
      {{ comments.count }}
      {% endfor %}






      django listview filtering






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 25 '18 at 11:20









      Lex IzmaylovLex Izmaylov

      545




      545
























          1 Answer
          1






          active

          oldest

          votes


















          1














          What you probably want is to .annotate(..) the queryset such that each Post object contains an extra attribute with the number of comments:



          from django.db.models import Count

          class PostListView(ListView):
          model = Post
          queryset = Post.objects.annotate(
          num_comments=Count('comment')
          )

          template_name = 'blog/home.html'
          context_object_name = 'posts'
          ordering = ['-date_posted']
          paginate_by = 5


          In the template, you can then fetch the .num_comment attribute (this is only added to Post objects that originate from this queryset), and render it with:



          {% for post in posts%}
          {{ post.content }}
          {{ post.num_comments }}
          {% endfor %}





          share|improve this answer



















          • 1





            Wow, thanks. Wasn't aware of this approach. Works really fine!

            – Lex Izmaylov
            Nov 25 '18 at 11:42











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466926%2ffiltering-another-model-field-count-for-each-item-from-object-list-list-view-d%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          What you probably want is to .annotate(..) the queryset such that each Post object contains an extra attribute with the number of comments:



          from django.db.models import Count

          class PostListView(ListView):
          model = Post
          queryset = Post.objects.annotate(
          num_comments=Count('comment')
          )

          template_name = 'blog/home.html'
          context_object_name = 'posts'
          ordering = ['-date_posted']
          paginate_by = 5


          In the template, you can then fetch the .num_comment attribute (this is only added to Post objects that originate from this queryset), and render it with:



          {% for post in posts%}
          {{ post.content }}
          {{ post.num_comments }}
          {% endfor %}





          share|improve this answer



















          • 1





            Wow, thanks. Wasn't aware of this approach. Works really fine!

            – Lex Izmaylov
            Nov 25 '18 at 11:42
















          1














          What you probably want is to .annotate(..) the queryset such that each Post object contains an extra attribute with the number of comments:



          from django.db.models import Count

          class PostListView(ListView):
          model = Post
          queryset = Post.objects.annotate(
          num_comments=Count('comment')
          )

          template_name = 'blog/home.html'
          context_object_name = 'posts'
          ordering = ['-date_posted']
          paginate_by = 5


          In the template, you can then fetch the .num_comment attribute (this is only added to Post objects that originate from this queryset), and render it with:



          {% for post in posts%}
          {{ post.content }}
          {{ post.num_comments }}
          {% endfor %}





          share|improve this answer



















          • 1





            Wow, thanks. Wasn't aware of this approach. Works really fine!

            – Lex Izmaylov
            Nov 25 '18 at 11:42














          1












          1








          1







          What you probably want is to .annotate(..) the queryset such that each Post object contains an extra attribute with the number of comments:



          from django.db.models import Count

          class PostListView(ListView):
          model = Post
          queryset = Post.objects.annotate(
          num_comments=Count('comment')
          )

          template_name = 'blog/home.html'
          context_object_name = 'posts'
          ordering = ['-date_posted']
          paginate_by = 5


          In the template, you can then fetch the .num_comment attribute (this is only added to Post objects that originate from this queryset), and render it with:



          {% for post in posts%}
          {{ post.content }}
          {{ post.num_comments }}
          {% endfor %}





          share|improve this answer













          What you probably want is to .annotate(..) the queryset such that each Post object contains an extra attribute with the number of comments:



          from django.db.models import Count

          class PostListView(ListView):
          model = Post
          queryset = Post.objects.annotate(
          num_comments=Count('comment')
          )

          template_name = 'blog/home.html'
          context_object_name = 'posts'
          ordering = ['-date_posted']
          paginate_by = 5


          In the template, you can then fetch the .num_comment attribute (this is only added to Post objects that originate from this queryset), and render it with:



          {% for post in posts%}
          {{ post.content }}
          {{ post.num_comments }}
          {% endfor %}






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 25 '18 at 11:25









          Willem Van OnsemWillem Van Onsem

          149k16144233




          149k16144233








          • 1





            Wow, thanks. Wasn't aware of this approach. Works really fine!

            – Lex Izmaylov
            Nov 25 '18 at 11:42














          • 1





            Wow, thanks. Wasn't aware of this approach. Works really fine!

            – Lex Izmaylov
            Nov 25 '18 at 11:42








          1




          1





          Wow, thanks. Wasn't aware of this approach. Works really fine!

          – Lex Izmaylov
          Nov 25 '18 at 11:42





          Wow, thanks. Wasn't aware of this approach. Works really fine!

          – Lex Izmaylov
          Nov 25 '18 at 11:42




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466926%2ffiltering-another-model-field-count-for-each-item-from-object-list-list-view-d%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          TypeError: fit_transform() missing 1 required positional argument: 'X'