DjangoでBootstrap4を用いたページネーションを設定する方法をご紹介します。
目次
条件
- Django 2.1.7
- Python 3.7.0
- Bootstrap4
前提
models.py
以下のようなModelが存在するものとします。
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
    def __str__(self):
        return self.username + ":" + self.email
class Post(models.Model):
    """投稿モデル"""
    class Meta:
        db_table = 'post'
    title = models.CharField(verbose_name='タイトル', max_length=255)
    text = models.CharField(verbose_name='内容', max_length=255, default='', blank=True)
    author = models.ForeignKey(
        'sample.CustomUser',
        on_delete=models.CASCADE,
    )
    created_at = models.DateTimeField(verbose_name='登録日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
    def __str__(self):
        return self.title + ',' + self.text
    @staticmethod
    def get_absolute_url(self):
        return reverse('sample:index')
DBレコード
以下のように10件のレコードが存在するものとします。
views.py
generic.ListViewを用いて「paginate_by = 3」を指定します。
import logging
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import generic
from .models import Post
logger = logging.getLogger('development')
class IndexView(LoginRequiredMixin, generic.ListView):
    paginate_by = 3
    template_name = 'sample/index.html'
    model = Post
ページネーションの実装
django-bootstrap4
以下のURLを参照して「django-bootstrap4」をインストールします。
https://pypi.org/project/django-bootstrap4/
base.html
以下はbase.htmlの抜粋です。
<!– Bootstrap4 –>で囲まれた箇所を記述して「django-bootstrap4」を読み込むようにします。
{% load staticfiles %}
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- Bootstrap4 -->
        {% load bootstrap4 %}
        {% bootstrap_css %}
        {% bootstrap_javascript jquery='full' %}
        <!-- Bootstrap4 -->
        <title>{% block title %}Blog{% endblock %}</title>
    </head>
pagination.html
base.htmlと同じディレクトリに以下のような「pagination.html」を作成します。
<div class="container">
    <div class="row">
        <div class="col-md-6 offset-md-3 py-2">
            <nav aria-label="ページ送り">
                <div class="text-center">
                    <ul class="pagination justify-content-center">
                        {% if page_obj.has_previous %}
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}">«</a></li>
                        {% else %}
                            <li class="page-item disabled"><span class="page-link">«</span></li>
                        {% endif %}
                        {% for i in page_obj.paginator.page_range %}
                            {% if page_obj.number == i %}
                                <li class="page-item active" aria-current="page">
                                    <a class="page-link" href="#">{{ i }} <span class="sr-only">(現位置)</span></a>
                                </li>
                            {% else %}
                                <li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
                            {% endif %}
                        {% endfor %}
                        {% if page_obj.has_next %}
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a></li>
                        {% else %}
                            <li class="page-item disabled"><span class="page-link">»</span></li>
                        {% endif %}
                    </ul>
                </div>
            </nav>
        </div>
    </div>
</div>
index.html
base.htmlをextendsして、pagination.htmlをincludeします。
{% extends 'base.html' %}
{% block content %}
<div class="col-lg-6 offset-lg-3">
    {% if user.is_authenticated %}
        <h1>ユーザ名</h1>
        <p class="user-name">{{ user.username }} でログイン中です。</p>
    {% endif %}
    <h1>Post List</h1>
    <section class="post-list">
        <ul>
            {% for post in object_list %}
            <li>
                <table class="table table-bordered">
                    <tbody>
                        <tr>
                            <th width="35%">タイトル</th>
                            <td width="65%">{{ post.title }}</td>
                        </tr>
                        <tr>
                            <th>内容</th>
                            <td>{{ post.text }}</td>
                        </tr>
                    </tbody>
                </table>
            </li>
            {% empty %}
            <li class="no-post">
                <p>記事が存在しません。</p>
            {% endfor %}
        </ul>
    </section>
    <div class="col-6 offset-3 justify-content-center">
        {% if is_paginated %}
            {% include 'pagination.html' %}
        {% endif %}
    </div>
</div>
{% endblock %}
実行結果
以下のように良い感じのページネーションが表示されます。
参考
How to Paginate with Django
https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html
Bootstrap4以降ガイド
https://cccabinet.jpn.org/bootstrap4/components/pagination
stackoverflow:Centering the pagination in bootstrap
https://stackoverflow.com/questions/15265253/centering-the-pagination-in-bootstrap
stackoverflow:Bootstrap 4 Center Pagination in Column
https://stackoverflow.com/questions/43679491/bootstrap-4-center-pagination-in-column

