【Django】ページネーションを作る

 

[speech_bubble type=”ln” subtype=”L1″ icon=”ilust/cat2_4_think.png” name=”ネコ”]ページネーションって何のことニャ?[/speech_bubble] [speech_bubble type=”ln” subtype=”L1″ icon=”profile_face.png” name=”のっくん”]ページネーションっていうのは、Google検索や掲示板の下の方にあるページの番号で移動できるリンクのことだよ。↓のやつだね。[/speech_bubble]

 

ページネーション

 

今回の記事では、このページネーションをDjangoで実装する方法について紹介します。

 

丁寧にコードを解説していきますので是非ご覧ください。

 

[toc]

 

ページネーション用のHTMLを作成

 

まず始めに、前に戻る矢印(<)や先に進む矢印(>)を表示するためのページを作ります。

 

pagination.html

<nav aria-label="Page navigation example">
  <ul class="pagination justify-content-center">

     <!-- 一番初めに戻る(<<) -->
     <li class="page-item">
         <a class="page-link" href="{% url 'board' %}/1" aria-label="Top">
            <span aria-hidden="true">&laquo;</span>
            <span class="sr-only">Top</span>
         </a>
     </li>

     <!-- 前に戻る(<) -->
      {% if page_active|add:"-1" > 0 %}
         <li class="page-item">
             <a class="page-link" href="{% url 'board' %}/{{ page_active|add:"-1" }}" aria-label="Previous">
                <span aria-hidden="true"><</span>
                <span class="sr-only">Previous</span>
             </a>
        </li>
      {% endif %}

    <!-- 数字列(1,2,3...) -->
    {% for anc in page%}
        {% if page_active == anc %}
            <li class="page-item active"><a class="page-link" href="{% url 'board' %}/{{ anc }}">{{anc}}
                <span class="sr-only">(current)</span></a></li>
        {% else%}
            <li class="page-item"><a class="page-link" href="{% url 'board' %}/{{ anc }}">{{anc}}</a></li>
        {% endif %}
    {% endfor %}

    <!-- 次に進む(>) -->
    {% if page_active|add:"1" <= page_last %}
        <li class="page-item">
          <a class="page-link" href="{% url 'board' %}/{{ page_active|add:"1" }}" aria-label="Next">
            <span aria-hidden="true">></span>
            <span class="sr-only">Next</span>
          </a>
        </li>
    {% endif %}

    <!-- 一番最後に進む(>>) -->
    <li class="page-item">
      <a class="page-link" href="{% url 'board' %}/{{page_last}}" aria-label="Last">
        <span aria-hidden="true">&raquo;</span>
        <span class="sr-only">Last</span>
      </a>
    </li>
  </ul>
</nav>

 

少し長いコードでしたね。これからじっくりこのページの内容を説明していきます。

 

Bootstrapを使用したページネーション

 

<nav>タグの中に<ul class=”pagination”></ul>を記載しています。その中に以下のタグを記載することでそれぞれのボタンが作成できます。

 

&nbsp;<li class="page-item"><a class="page-link" href="#"></a></li>

 

変数

 

{{ … }}で示される変数が出てきていますが、それぞれの変数の意味は以下の通り。

 

page: ページ番号が入ったリストです。1,2,3ページの場合、[1,2,3]が渡されます。

page_active: 現在どのページにいるか示す番号です。1から3のどれかの値が入ります。

page_last: 最後のページの番号です。例だと3が入ります。

 

値の渡し方については、ビューを使って渡す方法を後ほど説明します。

 

テンプレートタグ

 

ifタグを使って条件分岐しています。これらはテンプレートタグと呼ばれるものです。

 

例えば、1ページ目にいる場合は前に戻る「<」ボタンは表示しないようにしています。また、最後のページいる場合も次に進む「>」ボタンは表示しないようにしています。

 

1ページ目にいる場合に、page_active|add”-1″をしてしまうと0ページ目つまり存在しないページに飛んでしまうのでよろしくないからです。次に進むボタンに関しても同様です。

 

また、forタグを使って全てのページを表示するようにしています。このようにすることでページ数が増えても対応できます。

 

リンク先の設定

 

aタグで飛ぶリンク先ですが例では、~/board/1, ~/board/2, ~/board/3というようにページ番号がURLの後に入るようにしています。

 

urls.py

urlpatterns = [
    path('board', views.board, name='board'),
    path('board/<int:num>', views.board, name='board'),
}

 

このように記載することで、~/board、~/board/1、~/board/2、~/board/3のどれかにアクセスがあった場合には、views.pyのboardという関数が実行されるようになっています。

 

ビューの作成

 

上記で説明した変数ですが、pagination.htmlを呼び出す際に値の受け渡しをする必要があります。その処理はviews.pyのboard関数の中で行います。

 

views.py

def board(request, num=1):

    msgs = Message.objects.all()
    page = Paginator(msgs, 10)

    params = {
            'login_user': request.user,
            'contents': page.get_page(num),
            'page': page.page_range,   # list
            'page_active': num,          # intデータ
            'page_last': page.num_pages  # intデータ
        }

    return render(request, 'sns/board.html', params)

 

掲示板の例なので、関数名をboardとしています。引数にはnumが定義されています。boardもしくはboard/1にアクセスがあった場合は1が入ります。/board/2とアクセスがあった場合には、numは2になります。つまり現在のページを表す値がnumになります。

 

Message.objects.all()で掲示板に書かれた全てのメッセージを取得します。その後にPaginatorを使って、1ページ10個ずつ表示するようにしています。

 

page.get_pageで指定したページのメッセージを取得できます。page.page_rangeでページ番号のリスト、page.num_pagesでページ数を取得できます。

 

ページネーション用HTMLを呼び出す

 

先ほど作成したpagination.htmlを呼び出してみます。Djangoでは、呼び出したい箇所でincludeを使って以下のように書きます。

 

board.html

    :
{% include "sns/pagination.html" %}
    :

 

「run manage.py runserver」を実行して上記ページにアクセスすると以下のような表示が出てきます。

 

 

以上です。お疲れ様でした。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog