Djangoでページネーションを使う(django.core.paginator)

背景

  • 1画面に表示する件数が多かったので、ページネーションを追加する。
  • 標準のdjango.core.paginatorを使う
  • 環境は、Python 3.7.0 + Django 2.1.3

既存のコードの変更

views.pyの変更

  • from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger を追加

  • ページネーション用の関数を追加

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

# ページネーション用に、Pageオブジェクトを返す。
def paginate_query(request, queryset, count):
  paginator = Paginator(queryset, count)
  page = request.GET.get('page')
  try:
    page_obj = paginator.page(page)
  except PageNotAnInteger:
    page_obj = paginator.page(1)
  except EmptyPage:
    page_obj = paginatot.page(paginator.num_pages)
  return page_obj
  • リクエストを受け取る関数の変更
def myapp1(request):
  series = Series.objects.filter(deleted = False).order_by('-created_at')
  page_obj = paginate_query(request, series, settings.PAGE_PER_ITEM)   # ページネーション
  return render(request, 'app1/index.html', {'page_obj': page_obj, 'site_name':settings.SITE_NAME})  # モデルから取得したobjectsの代わりに、page_objを渡す

テンプレートの変更

  • モデルから取得したobjectsの代わりに、page_objを使って表示。
        {% for s in series %}
                <p>{{ s.title }}</p>
        {% endfor %}

を、seriesをpage_objに置き換える(for文の中身はそのままでよい)

        {% for s in page_obj %}
                <p>{{ s.title }}</p>
        {% endfor %}
  • ページネーション部分を追加(別ファイルに作成して、includeするとよい)
<div class="pagination">
    <span class="step-links">
        {% if page_obj.has_previous %}
            <a href="?page=1">« first</a>
            <a href="?page={{ page_obj.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
        </span>

        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">next</a>
            <a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
        {% endif %}
    </span>
</div>

設定ファイルに、1ページに表示する件数を指定

PAGE_PER_ITEM = 15

Bootstrap4を使って見映えをよくする

  • for文用のページ番号のリストを得るために、page_obj.paginator.page_rangeを使う
  • 他は、has_previous, previous_page_number, has_next, next_page_number, numberで指定する
<div>
    <nav aria-label="Page navigation example">
        <ul class="pagination">
            {% if page_obj.has_previous %}
                <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.previous_page_number }}">前</a></li>
            {% else %}
                <li class="disabled"><div class="page-link text-secondary d-inline-block disabled" href="#">前</div></li>
            {% endif %}

            {% for link_page in page_obj.paginator.page_range %}
                {% if link_page %}
                    {% if link_page == page_obj.number %}
                        <li class="disabled"><div class="page-link text-secondary d-inline-block disabled" href="#">{{ link_page }}</div></li>
                    {% else %}
                        <li><a class="page-link text-primary d-inline-block" href="?page={{ link_page }}">{{ link_page }}</a></li>
                    {% endif %}
                {% else %}
                    <li class="disabled"><a class="page-link text-secondary d-inline-block text-muted" href="#">・・・</a></li>
                {% endif %}
            {% endfor %}

            {% if page_obj.has_next %}
                <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.next_page_number }}">次</a></li>
            {% else %}
                <li class="disabled"><div class="page-link text-secondary d-inline-block disabled" href="#">次</div></li>
            {% endif %}
        </ul>
    </nav>
</div>
  • このような見映えになります。

スクリーンショット 2018-12-27 15.05.47.png

参考ページ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です