Kolya
Kolya

Reputation: 99

Pagination in detail view

I use a detail view for my posts in my blog and each post has comments so I want to paginate them but I don't konw how to do it because I did a request for the post model. I know how to do it in function view but not in detail view...

##view :
class PostDetailView(DetailView):
    model = Post
    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter(post_id=self.object.id).all()
        context['comments_number'] = Comment.objects.filter(post_id=self.object.id).count()
        context['form'] = CommentForm()
        return context


    def post(self, request, pk):
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = Post.objects.get(id=pk)
            comment.user = request.user
            comment.save()
            post = Post.objects.get(pk=pk)
            post.comments_nmb+=1
            post.save()
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))


##template:
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
  <div class="article-metadata">
    <a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
    <small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
    {% if object.author == user %}
      <div>
        <a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
        <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
      </div>
    {% endif %}
  </div>
  <h2 class="article-title">{{ object.title }}</h2>
  <p class="article-content">{{ object.content }}</p>
  <p>{{comments_number}} Comments</p>
 {%  for comment in comments %}
 <div class="media">                            
                        <a class="float-left">
                          <img class="rounded-circle account-img" src="{{ comment.user.profile.image.url }}">
                        </a>
                        <div class="media-body">

                          <h4 class="media-heading ">{{ comment.user.username }}</h4>
                          {{comment.text}}
                        </div>
                        <p class="float-right"><small>{{ comment.date}}</small></p>
                      </div>
{% endfor %}
</div>
</article>
{% endblock content %}

How to make pagination for comments in the for loop ?

Upvotes: 2

Views: 607

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477607

Almost exactly the same way:

from django.core.paginator import Paginator

class PostDetailView(DetailView):
    model = Post

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        page = self.request.GET.get('page')
        comments = Paginator(self.object.comment_set.all(), 25)
        context['comments'] = comments.get_page(page)
        context['comments_number'] = self.object.comment_set.count()
        context['form'] = CommentForm()
        return context

    # ...

We thus obtain the page parameter from the self.request.GET parameters, and we then make a Paginator and page it accordingly. You probably should also order the comments according to some field. Right now the comments can appear in any order, and thus the next page can contain comments that appeared on the previous page, etc.

The comments variable is thus a pagination object, and you can render it like you do in a function-based view.

Note that you can use comment_set (or if you set another related_name, that name) to access the set of attributes related to the Post object.

That being said, perhaps this is more a ListView over the comments, or a FormView, since you include a Form to comment.

Upvotes: 2

Related Questions