Menu
CoddyTech

Phân trang

Thuộc phần View dựa trên lớp trong hành trình Django của Coddy. Bài học 8 trên 18.

Trang công việc hiển thị tất cả công việc cùng lúc, và không thể chứa được một nghìn công việc. Phân trang (pagination) chia danh sách thành nhiều trang với các liên kết giữa chúng. ListView chia danh sách bằng một thuộc tính, paginate_by, cho biết số hàng trên mỗi trang.

Với paginate_by = 20 trong danh sách công thức nấu ăn, /recipes/ hiển thị 20 công thức đầu tiên, /recipes/?page=2 hiển thị 20 công thức tiếp theo, còn trang nằm ngoài phạm vi hoặc trang có số trang không hợp lệ sẽ trả về phản hồi 404. Danh sách trong mẫu chỉ chứa các hàng của trang hiện tại, và mẫu cũng nhận được is_paginated cùng page_obj, tức trang hiện tại.

Bạn tự viết các liên kết từ page_obj: number là số trang hiện tại, còn paginator.num_pages là tổng số trang. has_next và has_previous có giá trị True khi có trang sau hoặc trang trước trang này, còn next_page_number và previous_page_number cho biết số trang đó:

{% if page_obj.has_next %}
  <a href="?page={{ page_obj.next_page_number }}">More recipes</a>
{% endif %}

Luôn giữ điều kiện kiểm tra quanh mỗi liên kết: ở trang cuối, next_page_number gây ra lỗi khiến trang bị sập.

challenge icon

Thử thách

Dễ

Hiển thị 5 việc làm trên mỗi trang.

  1. Trong jobs/views.py, chỉnh JobListView để hiển thị 5 việc làm trên mỗi trang.
  2. Trong job_list.html, bên dưới danh sách, thêm <nav class="pages"> với các liên kết có nội dung chính xác là Previous và Next, cùng với Page 1 of 3 lấy từ page_obj ở giữa. Chỉ hiển thị mỗi liên kết khi có trang tương ứng, nếu không trang sẽ gặp lỗi.

Mở /jobs/ và nhấn Next: bạn sẽ thấy Page 2 of 3.

Tự làm thử

from django.views.generic import DetailView, ListView, TemplateView

from .models import Job


class HomeView(TemplateView):
    template_name = "jobs/home.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["count"] = Job.objects.count()
        context["latest"] = Job.objects.order_by("-posted").first()
        return context


class AboutView(TemplateView):
    template_name = "jobs/about.html"


class JobListView(ListView):
    model = Job
    context_object_name = "jobs"
    ordering = ["-posted"]

    def get_queryset(self):
        jobs = super().get_queryset()
        city = self.request.GET.get("city")
        if city:
            jobs = jobs.filter(city=city)
        return jobs


class JobDetailView(DetailView):
    model = Job

Tất cả bài học trong View dựa trên lớp

Tự luyện tập: Playground Django