djangoは多くのデータを扱いますので、ページネーションを作りたいという場合もあるかもしれません。
そこで今回は、ページネーションを作る方法を解説していきます。
ページネーションを作るにはPaginatorクラスとPageクラスを使います
djangoには、ページネーションを簡単に作ることができるように、PaginatorというクラスとPageというクラスがあらかじめ備えられています。
ですので、ここからはこれら2つを使って、どうやってページネーションを作るのかをお伝えしていきます。
Paginatorの使い方
Paginatorの作り方はコードをみていった方がイメージがわきやすいと思いますので、コードを見ていきましょう。
ベースコード(List,Detail)を使います。
まずはpaginatorオブジェクトを作る
まずはpaginatorオブジェクトを作ります。これは、Pagenatorクラスから作られるオブジェクトです。
AppModelにデータが10個入っていると仮定しましょう。
items = AppModel.objects.all()
paginator = Paginator(itmes, 3)
これでpaginaorオブジェクトができました。
今回は、10という引数を使ってpaginatorオブジェクトを作りました。これは、ページネーションのページ区切りを10記事毎にするという意味です。
つまり、今回はデータが10個ありますので、4ページからなるページネーションを作ったということになります。
paginatorオブジェクトから、pagesオブジェクトを作る
次に、paginatorオブジェクトからpagesオブジェクトを作っていきます。
このpagesオブジェクトの中に、ページネーションオブジェクトを作る上で必要な情報が入っています。
pagesオブジェクトを作るには、paginatorオブジェクトのpageメソッドを使います。
pages = paginator.page(1)
pageメソッドは最終的には、return Page(..)と、Pageクラスのオブジェクトを返すようになっていますので、pages = paginator.page()とすることでPageクラスから成るpagesオブジェクトを作ることができるのです。
コードの整理
ここまで書いてきたコードを改めて整理していきましょう。
コードclass appfunction(request):
items = AppModel.objects.all()
paginator = Paginator(items, 3)
pages = paginator.page(1)
return render(request, 'list.html', {'pages':pages})
このようなコードになります。
pagesオブジェクトでできること
ここから、pagesオブジェクトでできることを紹介していきます。ここを見ると、具体的なページネーションのイメージがわいてくると思います。
前提条件:データの数は10個、3個ずつ区切ったページネーションを作成、pagesオブジェクトの引数は1(1ページ目に関するデータ)
入力 | 出力 | 説明 |
pages | <Page 1 of 4> | 全ページと現在のページ |
pages.has_next() | True | 次のページがあるか |
pages.has_previous() | False | 前のページがあるか |
pages.has_other_pages() | True | 他のページがあるか |
pages.next_page_number() | 2 | 次のページの番号 |
pages.previous_page_number() | エラー | 前のページの番号 |
pages.start_index | 1 | ページの先頭の記事番号 |
pages.end_index | 3 | ページの最後の記事番号 |
これらのデータをhtmlファイルに埋め込んでいくことによって、ページネーションを作ることができます。
まずは簡単な表示をさせていきましょう。
コード-list.html
{{ pages.has_next }}
{{ pages.next_page_number }}
ブラウザではこのような表示になります。
次に、もう少しページネーションらしい形にしていきましょう。
views.pyの調整
今までは、pageは1に指定していましたが、これでは2ページ目をクリックしても、pagesオブジェクトに入るデータは1ページの情報になってしまいます。
ページに応じてpagesオブジェクトに入れるデータを変えるために、views.pyファイルを整えていきましょう。
具体的には、2ページ目をクリックしたら2ページ目の情報がpagesオブジェクトに入り、3ページ目をクリックしたら3ページ目の情報がpagesオブジェクトに入るようにします。
コードclass appfunction(request):
items = AppModel.objects.all()
paginator = Paginator(items, 3)
page = request.GET.get('page', 1)
pages = paginator.page(page)
try:
pages = paginator.page(page)
except PageNotAnInteger:
pages = paginator.page(1)
except EmptyPage:
pages = paginator.page(1)
return render(request, 'list.html', {'pages':pages})
request.GET.get('page', 1)で、urlに書かれているpageパラメータの数字を取るようにしています。もしurlにpageパラメータがなければ、1を返すようにしています。
この点があまりよくわからない方は、request.getとrequest.GET.getの違いという記事を参考にしてみてください。
また、try/except文では、pageのパラメーターがinteger型でない場合と、pageのパラメーターがページ数よりも大きい場合、1ページ目を出すように設定しています。
これで、urlで指定したpageパラメーターに応じてpaginationオブジェクトに入れるデータを調整することができるようになりました。
htmlファイルを整える
最後に、htmlファイルを整えていきましょう。
コード{% for item in pages %}
<tr>
<td>{{ item.title }}</td>
<td>{{ item.content }}</td>
</tr>
{% endfor %}
{% if users.has_other_pages %}
<ul>
{% if users.has_previous %}
<li><a href="?page={{ users.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in users.paginator.page_range %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endfor %}
{% if users.has_next %}
<li><a href="?page={{ users.next_page_number }}">»</a></li>
{% else %}
<li><span>»</span></li>
{% endif %}
</ul>
{% endif %}
これでページネーションの実装ができました。
ポイントは、最初のfor文です。{% for item in pages %}としており、pagesオブジェクトの中に、モデルのデータも入っていることを意識しておくとよいでしょう。
ClassBasedViewで実装
最後に、ClassvBasedViewでページネーションの実装を行っていきましょう。
ClassBasedViewでのページネーションの実装はびっくりするほど簡単です。
view.pyファイルをみていきましょう。
コードclass AppView(ListView):
model = AppModel
context_object_name = 'pages'
paginated_by = 10
これだけです。
このように、pagenated_byを設定するだけで、pagesオブジェクトが使えるようになります。
~Django無料講義~のご案内
Code for Djangoが、4時間超の無料Django講義をはじめました
- ・本を出版したCode for Djangoの 製作者が作ったサイトです。
- ・Code for Djangoの内容も、 動画で詳しく解説しています。
- ・動画は順次ふやしていきますので、 ただで学び続けることが可能です。
- ・Djangoの効率的なスキルアップに、 是非お役立て下さい。
