Django – Phân trang

4.6/5 - (9 votes)

Trong phần này chúng ta sẽ học cách phân trang. Django cung cấp lớp django.core.paginator hỗ trợ phân trang rất tốt.

Ví dụ

Chúng ta tạo một app có tên là pagination.

C:\Project\mysite>python manage.py startapp pagination

Thêm app vào danh sách INSTALLED_APPS:

INSTALLED_APPS = [
    #...
    'pagination',
    #...
]

Tiếp theo chúng ta tạo model và thêm vào một số dòng dữ liệu mẫu để test.

from django.db import models

# Create your models here.

class Customer(models.Model):
    name = models.CharField(max_length=100)
    country = models.CharField(max_length=20)

Chúng ta định nghĩa model Customer có 2 trường là namecountry.

Cập nhật lại CSDL:

python manage.py makemigrations
python manage.py migrate

Đoạn script sau sẽ tạo một số dòng dữ liệu mẫu trong bảng pagination_customer.

import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings");
django.setup()

from pagination.models import Customer

Customer.objects.create(name='Alfreds Futterkiste', country='Germany')
Customer.objects.create(name='Ana Trujillo Emparedados y helados', country='Mexico')
Customer.objects.create(name='Antonio Moreno Taquería', country='Mexico')
Customer.objects.create(name='Around the Horn', country='UK')
Customer.objects.create(name='Berglunds snabbköp', country='Sweden')
Customer.objects.create(name='Blauer See Delikatessen', country='Germany')
Customer.objects.create(name='Blondel père et fils', country='France')
Customer.objects.create(name='Bólido Comidas preparadas', country='Spain')
Customer.objects.create(name='Bon app', country='France')
Customer.objects.create(name='Bottom-Dollar Marketse', country='Canada')
Customer.objects.create(name='Bs Beverages', country='UK')
Customer.objects.create(name='Cactus Comidas para llevar', country='Argentina')
Customer.objects.create(name='Centro comercial Moctezuma', country='Mexico')
Customer.objects.create(name='Chop-suey Chinese', country='Switzerland')
Customer.objects.create(name='Comércio Mineiro', country='Brazil')
Customer.objects.create(name='Consolidated Holdings', country='UK')
Customer.objects.create(name='Drachenblut Delikatessend', country='Germany')
Customer.objects.create(name='Du monde entier', country='France')
Customer.objects.create(name='Eastern Connection', country='UK')

Tiếp theo chúng ta viết template và hàm view.

from django.shortcuts import render

# Create your views here.
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Customer

def listing(request): 
    customer_list = Customer.objects.all()
    paginator = Paginator(customer_list, 5)
 
    pageNumber = request.GET.get('page')
    try:
        customers = paginator.page(pageNumber)
    except PageNotAnInteger:
        customers = paginator.page(1)
    except EmptyPage:
        customers = paginator.page(paginator.num_pages)
 
    return render(request, 'list.html', {'customers':customers})

Chúng ta sử dụng lớp Pagination để thực hiện phân trang.

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

Đầu tiên chúng ta import một số lớp cần thiết.

paginator = Paginator(customer_list, 5)

Hàm khởi tạo Paginator() nhận vào 2 tham số, tham số đầu tiên là một đối tượng QuerySet, tham số thứ 2 là số tượng item trên mỗi “trang”. Trong ví dụ trên chúng ta đưa đối tượng customer_list vào với số lượng 5 item mỗi trang.

pageNumber = request.GET.get('page')

URL của chúng ta có thêm tham số page là số thứ tự của trang muốn xem.

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

Nếu tham số page không hợp lệ, chẳng hạn như page=abc thì Paginator sẽ giải phóng lỗi PageNotAnInterger, trong trường hợp này chúng ta trả về trang đầu tiên với phương thức Paginator.page(), hoặc nếu page nằm ngoài pham vi trang cho phép, chẳng hạn như chúng ta chỉ có 4 trang nhưng tham số page=1000 thì Paginator sẽ giải phóng lỗi EmptyPage, ở đây chúng ta xử lý bằng cách trả về trang cuối cùng bằng thuộc tính num_pages.

Template:

<table>
    <tr>
        <th>Customer name</th>
        <th>Country</th>
    </tr>
    {% for customer in customers %}
    <tr>
        <td>{{ customer.name }}</td>
        <td>{{ customer.country }}</td>
    </tr>
    {% endfor %}
</table>
<div class="pagination">
    <span class="step-links">
        {% if customers.has_previous %}
            <a href="?page={{ customers.previous_page_number }}">Previous</a>
        {% endif %}
    </span>

    <span class="current">
        Page {{ customers.number }} of {{ customers.paginator.num_pages }}.
    </span>
    
    <span>
        {% if customers.has_next %}
            <a href="?page={{ customers.next_page_number }}">Next</a>
        {% endif %}
    </span>
</div>

Cuối cùng chúng ta tạo URL và chạy server để xem kết quả.

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.listing),
]
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^pagination/', include('pagination.urls')),
]

Capture

1.5 2 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

12 Comments
Inline Feedbacks
View all comments
Đức PhạmTrung
Đức PhạmTrung
7 năm trước

Hay và rất hữu ích ạ 🙂

Lam
Lam
7 năm trước

hi. Ad hướng dẫn thêm cách cài đặt trên hosting với ạ

Văn Đức
Văn Đức
7 năm trước

Cảm ơn ad vì bài viết.
Mình xin góp ý là trong file pagination/views.py, dòng
return render(request, ‘list.html’, {‘customers’:customers}) phải chuyển thành
return render(request, ‘pagination/list.html’, {‘customers’:customers})

asdasd
6 năm trước

asdad

Khánh
Khánh
6 năm trước

Nếu bạn nào gặp lỗi này như mình thì thử cách này để fix nha:

Traceback (most recent call last):
  File ".\create_customer.py", line 7, in <module>
    django.setup()
  File "C:\Python27\lib\site-packages\django\__init__.py", line 22, in setup
    configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
  File "C:\Python27\lib\site-packages\django\conf\__init__.py", line 56, in __getattr__
    self._setup(name)
  File "C:\Python27\lib\site-packages\django\conf\__init__.py", line 41, in _setup
    self._wrapped = Settings(settings_module)
  File "C:\Python27\lib\site-packages\django\conf\__init__.py", line 110, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "C:\Python27\lib\importlib\__init__.py", line 37, in import_module
    __import__(name)
ImportError: No module named mysite.settings

======>

import os
    import sys
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    os.environ['DJANGO_SETTINGS_MODULE'] = 'YOURAPP.settings'
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "YOURAPP.settings")
Minh
Minh
6 năm trước

Admin cho minh hỏi: Mình chạy ra thanh phân trang, nhưng nội dung lại bị ẩn….
mà không hiện lỗi gì cả!!

Minh
Minh
6 năm trước
Reply to  Phở Code

Mình đã nhập dữ liệu rồi ad!!