utamaro’s blog

誰かの役に立つ情報を発信するブログ

Djangoでページングを表示するための関数

Djangoでページング処理を作成する際に作った関数を紹介します。

コードの紹介になるので、紹介はコードにコメントにて行います。

前後のページを表示するための関数

# self.limit: データ表示数
def page_data(self, count, page):
    # count: データ数
    # page: 現在のページ番号
    current_page = page
    if count == 0 or count < self.limit:
        # データ数が0の場合に対応
        prev_page = 1
        next_page = 1
        page_limit = 1
    else:
        # ページの最後尾の数値をみつける。
        page_num = int(count / self.limit)
        # 割り切れない場合は+1して、あまりを表示できるようにする
        page_limit = page_num if count % self.limit == 0 else page_num + 1

        # 前のページが1未満にならないようにする
        prev_page = 1 if (current_page - 1) < 1 else current_page - 1
        # 次のページがページ番号の限界を超えないようにする
        next_page = page_limit if (current_page + 1) > page_limit else current_page + 1
    return {
        'prev': prev_page,  # 前のページ
        'current': current_page,  # 現在のページ
        'next': next_page,  # 次のページ
        'limit': page_limit,  # ページの限界
        'next_page': 'home',  # {% url next_page %}のように使用する
    }

テンプレートのコードをなくしてしまったので紹介できません。orz

returnで返しているデータからhtmlタグを作成するとできます。

範囲でページを表示するための関数

もう少しスマートに作成する方法がありそうです。

def get_page_list(self, data_size, current_page):
    PAGE_RANGE_SIZE = 5  # ページ番号を表示する数
    if data_size % self.limit == 0:
        page_limit = int(data_size / self.limit)
    else:
        # 割り切れない場合は+1して、あまりを表示できるようにする
        page_limit = int(data_size / self.limit) + 1
    page_list = []
    # ↓ startとendを計算して、あとでループに使用する
    start = current_page - 2
    if start < 1:
        start = 1

    end = start + PAGE_RANGE_SIZE
    if end > page_limit:
        end = page_limit + 1
        # ↓ を入れないとページ番号がずれる
        start = end - PAGE_RANGE_SIZE
        if start < 1:
            start = 1

    # ページ番号を取得する
    for pi in range(start, end):
        page_list.append(pi)
    return {
        'current': current_page,  # 現在のページ
        'limit': page_limit,  # ページ番号の限界
        'nums': page_list,  # ページ番号のリスト
        'next_page': 'home',  # {% url next_page %}のように使用する
    }

テンプレートを作成する。

bulmaというcssフレームワークを使用していますが、基本は同じかと思います。

横に長くなってしまって見づらいです。どうにかしたいところです。

<ul class="pagination-list">
    {% if page.current != 1 %}
    <!-- 現在のページが先頭なら表示しない -->
    <li><a class="pagination-link" href="{% url page.next_page %}?{%query_transform request page=1%}"><<</a></li>
    {% endif %}
    {% for num in page.nums %}
    <li>
        <!-- 現在のページの場合はクラスを追加する -->
        <a class="pagination-link {% if num == page.current %} is-current {% endif %}" href="{% url page.next_page %}?{%query_transform request page=num%}">{{num}}</a>
    </li>
    {% endfor %}
    {% if page.current != page.limit %}
    <!-- 現在のページが最後尾なら表示しない -->
    <li><a class="pagination-link" href="{% url page.next_page %}?{%query_transform request page=page.limit%}">>></a></li>
    {% endif %}
</ul>

query_transformというのは独自に作ったtagです。

これを使うと、クエリストリングをスマートに作成できます。

@register.simple_tag
def query_transform(request, **kwargs):
    updated = request.GET.copy()
    for k, v in kwargs.items():
        updated[k] = v

    return updated.urlencode()

これはどこかの記事で紹介していた気がします。

stackoverflowで載っていたものを使っています。