首页 > 代码库 > Django 分页
Django 分页
Reference: https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html
How to Paginate with Django
As part of the Django’s common Web application tools, Django offers a few classes to manage paginated data. You can pass either a list/tuple of objects or an QuerySet. In this tutorial I will show how to paginate data using function based views and how to paginate using class-based views (ListView).
The Paginator
The paginator classes lives in django.core.paginator
. We will be working mostly with the Paginator
and Page
classes.
Consider the auth.User
table has 53 user instances.
from django.contrib.auth.models import Userfrom django.core.paginator import Paginatoruser_list = User.objects.all()paginator = Paginator(user_list, 10)
In the example above I’m telling Paginator
to paginate the user_list
QuerySet in pages of 10. This will create a 6 pages result. The first 5 pages with 10 users each and the last page with 3 users.
Debugging the Paginator Object
Input | Output | Type |
---|---|---|
paginator.count | 53 | <type ‘int‘> |
paginator.num_pages | 6 | <type ‘int‘> |
paginator.page_range | xrange(1, 7) | <type ‘xrange‘> |
paginator.page(2) | <Page 2 of 6> | <class ‘django.core.paginator.Page‘> |
The Paginator.page()
method will return a given page of the paginated results, which is an instance of Page
. This is what we will return to the template.
users = paginator.page(2)
Debugging the Page Object
Input | Output | Type |
---|---|---|
users | <Page 2 of 6> | <class ‘django.core.paginator.Page‘> |
users.has_next() | True | <type ‘bool‘> |
users.has_previous() | True | <type ‘bool‘> |
users.has_other_pages() | True | <type ‘bool‘> |
users.next_page_number() | 3 | <type ‘int‘> |
users.previous_page_number() | 1 | <type ‘int‘> |
users.start_index() | 11 | <type ‘int‘> |
users.end_index() | 20 | <type ‘int‘> |
The Page.next_page_number()
and Page.previous_page_number()
methods raises InvalidPage if next/previous page doesn’t exist.
The Page.start_index()
and Page.end_index()
are relative to the page number.
>>> users = paginator.page(6) # last page<Page 6 of 6>>>> users.start_index()51>>> users.end_index()53
The process is basically done by querying the database, then pass the QuerySet to the Paginator, grab a Page and return to the template. The rest is done in the template.
Let’s see now some practical examples.
Pagination with Function-Based Views
views.py
from django.contrib.auth.models import Userfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerdef index(request): user_list = User.objects.all() page = request.GET.get(‘page‘, 1) paginator = Paginator(user_list, 10) try: users = paginator.page(page) except PageNotAnInteger: users = paginator.page(1) except EmptyPage: users = paginator.page(paginator.num_pages) return render(request, ‘core/user_list.html‘, { ‘users‘: users })
user_list.html
<table class="table table-bordered"> <thead> <tr> <th>Username</th> <th>First name</th> <th>Email</th> </tr> </thead> <tbody> {% for user in users %} <tr> <td>{{ user.username }}</td> <td>{{ user.first_name }}</td> <td>{{ user.email }}</td> </tr> {% endfor %} </tbody></table>{% if users.has_other_pages %} <ul class="pagination"> {% if users.has_previous %} <li><a href=http://www.mamicode.com/"?page={{ users.previous_page_number }}">«</a></li> {% else %} <li class="disabled"><span>«</span></li> {% endif %} {% for i in users.paginator.page_range %} {% if users.number == i %} <li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li> {% else %} <li><a href=http://www.mamicode.com/"?page={{ i }}">{{ i }}</a></li> {% endif %} {% endfor %} {% if users.has_next %} <li><a href=http://www.mamicode.com/"?page={{ users.next_page_number }}">»</a></li> {% else %} <li class="disabled"><span>»</span></li> {% endif %} </ul>{% endif %}
The result is something like this:
The example above is using Bootstrap 3.
Pagination with Class-Based Views
views.py
class UserListView(ListView): model = User template_name = ‘core/user_list.html‘ # Default: <app_label>/<model_name>_list.html context_object_name = ‘users‘ # Default: object_list paginate_by = 10 queryset = User.objects.all() # Default: Model.objects.all()
user_list.html
<table class="table table-bordered"> <thead> <tr> <th>Username</th> <th>First name</th> <th>Email</th> </tr> </thead> <tbody> {% for user in users %} <tr> <td>{{ user.username }}</td> <td>{{ user.first_name }}</td> <td>{{ user.email }}</td> </tr> {% endfor %} </tbody></table>{% if is_paginated %} <ul class="pagination"> {% if page_obj.has_previous %} <li><a href=http://www.mamicode.com/"?page={{ page_obj.previous_page_number }}">«</a></li> {% else %} <li class="disabled"><span>«</span></li> {% endif %} {% for i in paginator.page_range %} {% if page_obj.number == i %} <li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li> {% else %} <li><a href=http://www.mamicode.com/"?page={{ i }}">{{ i }}</a></li> {% endif %} {% endfor %} {% if page_obj.has_next %} <li><a href=http://www.mamicode.com/"?page={{ page_obj.next_page_number }}">»</a></li> {% else %} <li class="disabled"><span>»</span></li> {% endif %} </ul>{% endif %}
Django 分页