1

My problem is similar to this problem. The only difference is I use GCBV for my pagination. My view file is as follows:

class ChatListView(ListView):
    model = Chat
    form_class = NewMessageForm
    template_name = 'chat.html'
    paginate_by = 5
    queryset = model.objects.all() ###not needed


    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)        
        if form.is_valid():
            form.save()
            return redirect('chat') <--- here
        return render(request, self.template_name, {'form': form})

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)  
        context['form'] = NewMessageForm() # edited: self.form_class
        return context

What I want the post method to redirect to the last page of the pagination. In the link, it was achieved by return HttpResponseRedirect('/forum/topic/%s/?page=%s' % (topic.slug, posts.num_pages)). But for my GCBV, I don't know how to get the .num_pages via an object. A little help please.

user8703143
  • 173
  • 1
  • 14
  • `queryset = form_class.objects.all()` doesn't make sense. It should be something like `queryset = Chat.objects.all()`. However in this case you don't have to set `queryset` at all, because you have `model = Chat`. – Alasdair Jan 04 '18 at 11:44
  • Also, note that you use `self.form_class` in `post` but `NewMessageForm` in `get`, which is inconsistent. – Alasdair Jan 04 '18 at 11:52
  • Yes. Edited queryset. It's a typo. But when I don't add queryset, the objects in my database don't show up. Maybe it's conflicting with the post method(I'm not sure) but queryset solves the problem. – user8703143 Jan 04 '18 at 11:54
  • I thought `self.form_class` points to `NewMessageForm` . Should I change it to the latter? – user8703143 Jan 04 '18 at 11:56
  • It would be better if you could remove `queryset = model.objects.all() `, since it shouldn't be necessary. Looking at [the internals](https://github.com/django/django/blob/master/django/views/generic/list.py#L9), you might have to set `self.object_list = self.get_queryset()` for the `get_context_data` to work in the `post` request. – Alasdair Jan 04 '18 at 12:06
  • Yes, `self.form_class = NewMessageForm`. My point is that it's inconsistent to use `NewMessageForm` in one method and `self.form_class` in the other. Using `self.form_class` is more DRY, but in this case, the code might be more readable if you use `NewMessageForm` in both methods and remove `self.form_class`. – Alasdair Jan 04 '18 at 12:08

1 Answers1

2

You could call get_context_data, which will paginate the queryset and include paginator in the context. You can then access the number of pages with paginator.num_pages.

from django.urls import reverse

class ChatListView(ListView):
    ...

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)        
        if form.is_valid():
            form.save()
            self.object_list = self.get_queryset()  # get_context_data expects self.object_list to be set
            context = self.get_context_data()
            paginator = context['paginator']
            num_pages = paginator.num_pages
            return redirect(reverse('chat') + '?page=%s' % paginator.num_pages)
Alasdair
  • 298,606
  • 55
  • 578
  • 516