DjangoのListViewにページネーションを実装する
- 公開日:2018/10/19
- 更新日:2019/01/18
- 投稿者:n bit
Djangoのリスト形式(ListView)で投稿内容が増えてくるとページ送りが必要になってきます。今回はListViewで基本的なページネーションを実装する方法を解説します。コピーアンドペーストですぐに使えるサンプルコード付です。
この記事は約 分で読めます。(文字)
DjangoのListViewにページネーションを実装
ブログなどではよく利用されているページネーション(ページ送り)。Djangoでも投稿したページ数が増えてくるとスクロール量が増えすぎるためページネーションの必要性が発生します。
DjangoのListViewでは標準でページネーションのための機能が実装されていますので簡単にページネーションを利用することができます。基本的なコードの解説と、コピーアンドペーストで利用できるサンプルコードを掲載しておきます。
ListViewで1ページに表示させる記事数を指定する
ListViewのクラス属性に『paginate_by』を使って1ページ内に表示させる件数を指定します。
- paginate_by =1ページ内に表示させる件数
ListViewのクラス属性に実際に指定した事例は下記の通りです。1ページごとに12件ずつ表示するように設定しています。
class PostIndexView(generic.ListView):
・
・
・
paginate_by = 12
ページネーション用のテンプレート作成
ページネーション用のテンプレートはBootstrap4を利用して作成するのが簡単です。基本となるコードは以下のようになります。
<nav aria-label="ページネーション">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="前へ">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{% for page_num in page_obj.paginator.page_range %}
{% if page_num == page_obj.number %}
<li class="page-item active">
<a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="次へ">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
クラスの指定などはデザインに合わせて適宜変更してください。
- 参考:Bootstrap4サンプルコード:Pagination · Bootstrap
Djangoのテンプレートコードについて少し解説しておきます。
前のページが存在するか判定
{% if page_obj.has_previous %}
は、現在のページに対して前のページが存在するかどうかの判定です。前のページが存在する場合は『True』を返します。
前のページ番号を出力
{{ page_obj.previous_page_number }}
は、前のページのページ番号を出力します。前のページが存在しない時は『InvalidPage』エラーが出力されてしまうため『{% if page_obj.has_previous %}』で事前の分岐が必要です。
ページ数の範囲を出力
{% for page_num in page_obj.paginator.page_range %}
は、ページ数の範囲を1から順に出力するイテレータです。全部で5Pあれば1〜5を順番に出力し変数『page_num』に格納します。
現在のページ番号取得
{% if page_num == page_obj.number %}
は、『page_num』に格納されたページ番号と現在のページ番号が一致するかの判定です。『page_obj.number』で現在のページ番号を取得。
一致する場合はクラス『active』付のコード、一致しない場合はクラス『active』なしのコードを出力します。
次のページが存在するか判定
{% if page_obj.has_next %}
は、現在のページに対して次のページが存在するかどうかの判定です。次のページが存在する場合は『True』を返します。
次のページ番号を出力
{{ page_obj.next_page_number }}
は、次のページのページ番号を出力します。次のページが存在しない時は『InvalidPage』エラーが出力されてしまうため『{% if page_obj.has_next %}』で事前の分岐が必要です。
Djangoのページネーションで必要となる基本的なコードはこれだけです。記述できれば『pagenation-list.html』と言うファイル名で保存しましょう。
標準で機能が実装されているため特別に関数などを組む必要はありません。
ページテンプレートにページネーションのテンプレートをインクルード
ページテンプレートの任意の位置 (ページネーションを設置したい位置)に下記コードをペーストしてください。
- ※:ページネーションテンプレートの保存名が『pagenation-list.html』の場合
{% include 'app/pagenation-list.html' %}
これで先ほど作成したページネーションのテンプレートがインクルードされて出力されます。今回のようなテンプレートをインクルード形式で保持しておけば使い回しも簡単にできるので便利です。
今日のdot
Djangoで基本的なページネーションを作成するのは今回見て分かるようにとても簡単です。しかし、任意の位置で省略したページネーションの出力や、ページコンテンツのフィルタリングと合わせて動作するページネーションを作成するには少し工夫が必要です。
それらのコードについてはまた別のページで解説します。