Pagination
Part of the Class-Based Views section of Coddy's Django journey. Lesson 8 of 18.
The jobs page shows every job at once, and a thousand would not fit. Pagination splits a list into pages with links between them. A ListView does the splitting with one attribute, paginate_by, the rows per page.
With paginate_by = 20 on a recipe list, /recipes/ shows the first 20, /recipes/?page=2 the next 20, and a page past the end answers 404. The template's list holds only this page's rows, and the template also gets is_paginated and page_obj, the current page.
The links are yours to write. page_obj knows number, paginator.num_pages, has_next, next_page_number, has_previous and previous_page_number:
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">More recipes</a>
{% endif %}Keep the test around every link: on the last page, next_page_number raises an error that crashes the page.
Challenge
EasyShow the jobs 5 per page:
- In
JobListView, 5 rows per page. - In
job_list.html, under the list, a<nav class="pages">with aPreviouslink, the textPage 1 of 3(real numbers) and aNextlink. Each link shows only when its page exists.
Press Run, open /jobs/ and press Next.
Try it yourself
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
All lessons in Class-Based Views
Practice on your own: Django playground