2

I have a quick logical question regarding Django class-based view method get_context_data().

Imagine I have a paginated class-based ListView. It shows 20 objects per page, and there are 200 objects in the entire queryset.

My question is:

How do I iterate over only those objects in context["object_list"] that are part of the current page?

Hassan Baig
  • 15,055
  • 27
  • 102
  • 205

1 Answers1

3

It is very simple when using a class-based view.

In views.py:

from django.views.generic import ListView


class YourPaginatedListView(ListView):
    ...
    paginate_by = 20

In your template, some version of this:

 {% if is_paginated %}
  <nav>
    <ul>

      <li>
        <a href="{% if page_obj.has_previous %}?page=1{% endif %}">
          First Page
        </a>
      </li>

      <li>
        <a href="{% if page_obj.has_previous %}?page={{ page_obj.previous_page_number }}{% endif %}">
          Previous Page
        </a>
      </li>

      <li>
        <a>{{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</a>
      </li>

      <li>
        <a href="{% if page_obj.has_next %}?page={{ page_obj.next_page_number }}{% endif %}">
          Next Page
        </a>
      </li>

      <li>
        <a href="{% if page_obj.has_next %}?page={{ page_obj.paginator.num_pages }}{% endif %}">
          Last Page
        </a>
      </li>

    </ul>
  </nav>
{% endif %}

If you are not using a CBV, take a look at the docs for Using Paginator in a view.

Update:

Since you are processing the object list, try something like this in your view to only process the objects on the current page:

from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator

from .models import YourModel


class YourPaginatedListView(ListView):
    ...
    paginate_by = 20

    def get_context_data(self, **kwargs):

        context = super(YourPaginatedListView, self).get_context_data(**kwargs) 
        object_list = YourModel.objects.all()

        paginator = Paginator(object_list, self.paginate_by)
        page = self.request.GET.get('page')

        try:
            current_objects = paginator.page(page)
        except PageNotAnInteger:
            current_objects = paginator.page(1)
        except EmptyPage:
            current_objects = paginator.page(paginator.num_pages)

        # Process the objects on the current page here

        context['object_list'] = current_objects
        return context
Mike Covington
  • 2,147
  • 1
  • 16
  • 26
  • I'm using a CBV. So isn't there a solution I can implement directly in the view, e.g. in get_context_data() or something? – Hassan Baig Nov 13 '15 at 06:11
  • All you need to do is add `paginate_by = 20` (or whatever #) and the rest is 'magic'. The `object_list` that gets passed to the template should only contain the current page's objects and all of the pagination variables (`is_paginated`, `page_obj`) get added to context, too. – Mike Covington Nov 13 '15 at 06:14
  • Are you manually overriding `object_list`? If so, that might be causing problems. – Mike Covington Nov 13 '15 at 06:15
  • Here is a working example that I recently wrote: `views.py` - https://github.com/mfcovington/django-system-maintenance/blob/develop/system_maintenance/views.py#L82 and template - https://github.com/mfcovington/django-system-maintenance/blob/develop/system_maintenance/templates/system_maintenance/_pagination.html (it has some extra classes because I'm using bootstrap) – Mike Covington Nov 13 '15 at 06:18
  • Actually Mike, I'm running a DB call while iterating through the object_list in get_context_data(). It's currently going over the entire queryset. I was wondering if I could just limit those calls to the objects in the page. DB calls within a for loop are really killing my performance. – Hassan Baig Nov 13 '15 at 06:20
  • Another user iterated over all objects, but ignored those not in the current page: http://stackoverflow.com/questions/5907575/how-do-i-use-pagination-with-django-class-based-generic-listviews#comment36298497_5910325 However, I think there is a better way which would include something from here: https://docs.djangoproject.com/en/1.8/topics/pagination/ I'm gonna mess around with it. – Mike Covington Nov 13 '15 at 06:26
  • 1
    Updated w/ a possible solution. – Mike Covington Nov 13 '15 at 06:39
  • Thanks Mike, I'll take it for a spin. – Hassan Baig Nov 13 '15 at 08:23