Search code examples
djangopaginationdjango-filterdjango-paginationdjango-filters

How to paginate a class-based list view with django-filters


Do you guys know how to paginate a generic class-based ListView that uses django-filters as a search bar? When I read some articles regarding this issue(which wasn't a lot for class-based views), it seems that django-filters and pagination don't work together very well. Here is my view:

class StudentListView(OrganisorAndLoginRequiredMixin, generic.ListView):
    template_name = "leads/student_list.html"
    context_object_name = "leads"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = StudentFilter(self.request.GET, queryset=self.get_queryset())
        return context

    def get_queryset(self):
        organisation = self.request.user.userprofile
        return Lead.objects.filter(organisation=organisation).order_by('first_name')

I would really appreciate it if you guys could tell me what code I need to write for my view as well as what code I need to add into my template to make pagination work. I don't think the code for the actual filter and the template is necessary, but if you guys need it, I can add it to this question. Thanks.

For additional information, I am going to add the following pagination code to my template:

{% if is_paginated %}
  <div class="pagination">
      <span class="page-links">
          {% if page_obj.has_previous %}
              <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a>
          {% endif %}
          <span class="page-current">
              Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
          </span>
          {% if page_obj.has_next %}
              <a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a>
          {% endif %}
      </span>
  </div>
{% endif %}

Solution

  • You should use FilterView that is provided by django-filter. Also this class inherits from MultipleObjectMixin so it is capable of performing pagination, so if you set paginate_by attribute on the class it will perform pagination too:

    from django_filters.views import FilterView
    
    
    class StudentListView(OrganisorAndLoginRequiredMixin, FilterView):
        template_name = "leads/student_list.html"
        context_object_name = "leads"
        filterset_class = StudentFilter
        paginate_by = 10 # Change as per your preference
        
        def get_queryset(self):
            organisation = self.request.user.userprofile
            return Lead.objects.filter(organisation=organisation).order_by('first_name')