ページネーション
CoddyのDjangoジャーニー「クラスベースビュー」セクションの一部。レッスン 8/18。
求人ページにはすべての求人が一度に表示されますが、1,000件では収まりません。ページネーションでは、リストを複数のページに分け、ページ間をリンクでつなぎます。ListViewでは、1つの属性paginate_byで分割し、1ページあたりの行数を指定します。
レシピ一覧にpaginate_by = 20を設定すると、/recipes/には最初の20件が表示され、/recipes/?page=2には次の20件が表示されます。最後のページを超えるページや、数字ではないページを指定すると、404レスポンスが返されます。テンプレートのリストにはこのページの行だけが含まれ、テンプレートには現在のページを表すis_paginatedとpage_objも渡されます。
リンクはpage_objを使って自分で記述します。numberはこのページの番号、paginator.num_pagesはページ数です。has_nextとhas_previousは、このページの後または前にページがある場合にTrueになり、next_page_numberとprevious_page_numberでそのページ番号を取得できます。
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">More recipes</a>
{% endif %}各リンクを囲む条件判定は必ず残してください。最後のページでは、next_page_numberを呼び出すとエラーが発生し、ページがクラッシュします。
チャレンジ
簡単1ページあたり5件の求人を表示します。
jobs/views.pyで、JobListViewが1ページあたり5件の求人を表示するようにします。job_list.htmlで、一覧の下に<nav class="pages">を追加し、「Previous」と「Next」と正確に表示するリンクを配置します。その間には、page_objを使ってPage 1 of 3を表示します。各リンクは、そのページが存在する場合にのみ表示してください。そうしないとページがクラッシュします。
/jobs/を開いてNextを押すと、Page 2 of 3が表示されます。
自分で試してみよう
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
クラスベースビューのすべてのレッスン
自分で練習してみよう: Djangoプレイグラウンド