1. ==========
    
  2. Pagination
    
  3. ==========
    
  4. 
    
  5. Django provides high-level and low-level ways to help you manage paginated data
    
  6. -- that is, data that's split across several pages, with "Previous/Next" links.
    
  7. 
    
  8. The ``Paginator`` class
    
  9. =======================
    
  10. 
    
  11. Under the hood, all methods of pagination use the
    
  12. :class:`~django.core.paginator.Paginator` class. It does all the heavy lifting
    
  13. of actually splitting a ``QuerySet`` into :class:`~django.core.paginator.Page`
    
  14. objects.
    
  15. 
    
  16. Example
    
  17. =======
    
  18. 
    
  19. Give :class:`~django.core.paginator.Paginator` a list of objects, plus the
    
  20. number of items you'd like to have on each page, and it gives you methods for
    
  21. accessing the items for each page::
    
  22. 
    
  23.     >>> from django.core.paginator import Paginator
    
  24.     >>> objects = ['john', 'paul', 'george', 'ringo']
    
  25.     >>> p = Paginator(objects, 2)
    
  26. 
    
  27.     >>> p.count
    
  28.     4
    
  29.     >>> p.num_pages
    
  30.     2
    
  31.     >>> type(p.page_range)
    
  32.     <class 'range_iterator'>
    
  33.     >>> p.page_range
    
  34.     range(1, 3)
    
  35. 
    
  36.     >>> page1 = p.page(1)
    
  37.     >>> page1
    
  38.     <Page 1 of 2>
    
  39.     >>> page1.object_list
    
  40.     ['john', 'paul']
    
  41. 
    
  42.     >>> page2 = p.page(2)
    
  43.     >>> page2.object_list
    
  44.     ['george', 'ringo']
    
  45.     >>> page2.has_next()
    
  46.     False
    
  47.     >>> page2.has_previous()
    
  48.     True
    
  49.     >>> page2.has_other_pages()
    
  50.     True
    
  51.     >>> page2.next_page_number()
    
  52.     Traceback (most recent call last):
    
  53.     ...
    
  54.     EmptyPage: That page contains no results
    
  55.     >>> page2.previous_page_number()
    
  56.     1
    
  57.     >>> page2.start_index() # The 1-based index of the first item on this page
    
  58.     3
    
  59.     >>> page2.end_index() # The 1-based index of the last item on this page
    
  60.     4
    
  61. 
    
  62.     >>> p.page(0)
    
  63.     Traceback (most recent call last):
    
  64.     ...
    
  65.     EmptyPage: That page number is less than 1
    
  66.     >>> p.page(3)
    
  67.     Traceback (most recent call last):
    
  68.     ...
    
  69.     EmptyPage: That page contains no results
    
  70. 
    
  71. .. note::
    
  72. 
    
  73.     Note that you can give ``Paginator`` a list/tuple, a Django ``QuerySet``,
    
  74.     or any other object with a ``count()`` or ``__len__()`` method. When
    
  75.     determining the number of objects contained in the passed object,
    
  76.     ``Paginator`` will first try calling ``count()``, then fallback to using
    
  77.     ``len()`` if the passed object has no ``count()`` method. This allows
    
  78.     objects such as Django's ``QuerySet`` to use a more efficient ``count()``
    
  79.     method when available.
    
  80. 
    
  81. .. _paginating-a-list-view:
    
  82. 
    
  83. Paginating a ``ListView``
    
  84. =========================
    
  85. 
    
  86. :class:`django.views.generic.list.ListView` provides a builtin way to paginate
    
  87. the displayed list. You can do this by adding a
    
  88. :attr:`~django.views.generic.list.MultipleObjectMixin.paginate_by` attribute to
    
  89. your view class, for example::
    
  90. 
    
  91.     from django.views.generic import ListView
    
  92. 
    
  93.     from myapp.models import Contact
    
  94. 
    
  95.     class ContactListView(ListView):
    
  96.         paginate_by = 2
    
  97.         model = Contact
    
  98. 
    
  99. This limits the number of objects per page and adds a ``paginator`` and
    
  100. ``page_obj`` to the ``context``. To allow your users to navigate between pages,
    
  101. add links to the next and previous page, in your template like this:
    
  102. 
    
  103. .. code-block:: html+django
    
  104. 
    
  105.     {% for contact in page_obj %}
    
  106.         {# Each "contact" is a Contact model object. #}
    
  107.         {{ contact.full_name|upper }}<br>
    
  108.         ...
    
  109.     {% endfor %}
    
  110. 
    
  111.     <div class="pagination">
    
  112.         <span class="step-links">
    
  113.             {% if page_obj.has_previous %}
    
  114.                 <a href="?page=1">&laquo; first</a>
    
  115.                 <a href="?page={{ page_obj.previous_page_number }}">previous</a>
    
  116.             {% endif %}
    
  117. 
    
  118.             <span class="current">
    
  119.                 Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
    
  120.             </span>
    
  121. 
    
  122.             {% if page_obj.has_next %}
    
  123.                 <a href="?page={{ page_obj.next_page_number }}">next</a>
    
  124.                 <a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
    
  125.             {% endif %}
    
  126.         </span>
    
  127.     </div>
    
  128. 
    
  129. .. _using-paginator-in-view:
    
  130. 
    
  131. Using ``Paginator`` in a view function
    
  132. ======================================
    
  133. 
    
  134. Here's an example using :class:`~django.core.paginator.Paginator` in a view
    
  135. function to paginate a queryset::
    
  136. 
    
  137.     from django.core.paginator import Paginator
    
  138.     from django.shortcuts import render
    
  139. 
    
  140.     from myapp.models import Contact
    
  141. 
    
  142.     def listing(request):
    
  143.         contact_list = Contact.objects.all()
    
  144.         paginator = Paginator(contact_list, 25) # Show 25 contacts per page.
    
  145. 
    
  146.         page_number = request.GET.get('page')
    
  147.         page_obj = paginator.get_page(page_number)
    
  148.         return render(request, 'list.html', {'page_obj': page_obj})
    
  149. 
    
  150. In the template :file:`list.html`, you can include navigation between pages in
    
  151. the same way as in the template for the ``ListView`` above.