【django】ListViewでページ送りを実装する方法 (paginate_by)

ページ送りとは,ページネーションと呼ばれ,複数の要素をページごとにわけて表示することです

何も対策していないと,1ページにデータベースの中身全てを出力することになり,サーバーへのアクセスがパンパンになってアンパンマンになります

本記事では,ListViewでデータベースの中身を出力する際に,ページ送りを実装する方法について解説します

ListViewの基本的な使い方は下記記事を参照してください

目次

ListViewのpagenated_byでページネーションの要素数を指定する

ListViewでは,クラス変数にページごとに表示する要素数を簡単に指定できます

クラス変数にpaginated_byを追加し,要素数を数値で指定してください

class BlogListView(ListView):
    model = Blog
    template_name = 'blog/blog.html'
    context_object_name = 'results'
    paginate_by = 3

ページ送りを実装するTemplateを準備する

直接実装したいテンプレートに書いても良いですが,長くなるので専用のものを用意します

{% if is_paginated %}
    {% if page_obj.has_previous %}
        <a class="btn btn-outline-primary mb-4" href="?page=1">
            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="24" fill="currentColor" class="bi bi-skip-start" viewBox="0 0 16 16">
                <path d="M4 4a.5.5 0 0 1 1 0v3.248l6.267-3.636c.52-.302 1.233.043 1.233.696v7.384c0 .653-.713.998-1.233.696L5 8.752V12a.5.5 0 0 1-1 0V4zm7.5.633L5.696 8l5.804 3.367V4.633z"/>
            </svg>
        </a>
        <a class="btn btn-outline-primary mb-4" href="?page={{page_obj.previous_page_number}}">
            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="24" fill="currentColor" class="bi bi-caret-left" viewBox="0 0 16 16">
                <path d="M10 12.796V3.204L4.519 8 10 12.796zm-.659.753l-5.48-4.796a1 1 0 0 1 0-1.506l5.48-4.796A1 1 0 0 1 11 3.204v9.592a1 1 0 0 1-1.659.753z"/>
            </svg>
        </a>
    {% endif %}

    {% for num in page_obj.paginator.page_range %}
        {% if page_obj.number == num %}
        <a class="btn btn-primary mb-4" href="?page={{num}}">{{ num }}</a>
        {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
        <a class="btn btn-outline-primary mb-4" href="?page={{num}}">{{ num }}</a>
        {% endif %}
    {% endfor %}

    {% if page_obj.has_next %}
        <a class="btn btn-outline-primary mb-4" href="?page={{page_obj.next_page_number}}">
            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="24" fill="currentColor" class="bi bi-caret-right" viewBox="0 0 16 16">
                <path d="M6 12.796V3.204L11.481 8 6 12.796zm.659.753l5.48-4.796a1 1 0 0 0 0-1.506L6.66 2.451C6.011 1.885 5 2.345 5 3.204v9.592a1 1 0 0 0 1.659.753z"/>
            </svg>
        </a>
        <a class="btn btn-outline-primary mb-4" href="?page={{page_obj.paginator.num_pages}}">
            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="24" fill="currentColor" class="bi bi-skip-end" viewBox="0 0 16 16">
                <path d="M12.5 4a.5.5 0 0 0-1 0v3.248L5.233 3.612C4.713 3.31 4 3.655 4 4.308v7.384c0 .653.713.998 1.233.696L11.5 8.752V12a.5.5 0 0 0 1 0V4zM5 4.633L10.804 8 5 11.367V4.633z"/>
            </svg>
        </a>
    {% endif %}
{% endif %}

用意した上記のpagination.htmlをListViewで使用しているテンプレートにincludeします

本記事ではblog.htmlに実装します

{% block main %}
    <div class="text-center mb-5">
        <h1 class="display-3 mb-5">はやてれおのBlog</h1>
        <p class="text-muted fs-3">Blogの記事一覧</p>
    </div>
    <div>
        {% for result in results %}
        <h4>{{ result.title }}</h4>
        <p>{{ result.created_at }}</p>
        <p class="lead">{{ result.content }}</p>
        {% endfor %}
    </div>
    {% include 'blog/pagination.html' %} <!--追加-->
{% endblock %}

includeの引数はクォーテーションでくくるのを忘れないようにしてください

ページ送りの動作確認

では動作を確認しましょう

下記コマンドを実行してサーバーを立ち上げて確認してみてください

python manage.py runserver

参考文献

お疲れ様でした

シェアしてくださると嬉しいです!
  • URLをコピーしました!

コメント

コメントする

目次