3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Djangoのページネーション実装でページあたりのコンテンツ数を変更できるように

Posted at

はじめに

Djangoでページネーションの実装を行う必要があった。
その際、ページあたりのコンテンツの表示数を変更できるような実装を行いたかった。
今回は記事の一覧表示を行うアプリケーションを参考に実装方法を示す。

環境

  • Python 3.7.3
  • Django 2.1.6
  • bootstrap4

Model

app/models.py
from django.db import models

class Article(models.Model):
  title = models.CharField('title', max_length=255)
  content = models.CharField('content', max_length=255)

Form

コンテンツの表示数を10〜50で変更できるようにしている。
また、今回はセレクトボックスで値を選択した時点で、submitも行いたいため、
widget=forms.Select(attrs={'onchange': 'submit(this.form);})
のようにしている。

app/forms.py
from django import forms

PAGINATE_BY_CHOICES = (
  ('', '-'*10),
  (10, '10'),
  (20, '20'),
  (30, '30'),
  (40, '40'),
  (50, '50')
)

class Paginate(forms.Form):
  paginate_by = forms.ChoiceField(
    label='記事表示数',
    widget=forms.Select(attrs={'onchange': 'submit(this.form);'}),
    choices=PAGENATE_BY_CHOICES
  )

View

Viewはdjango.view.Viewを利用している。現在Djangoを勉強中のため、むやみに汎用ビューを使いたくないという理由からです。
デフォルトではページあたり10個の記事を表示します。
また、セッションに選択したページあたりのコンテンツ数を保存することで、ページ遷移しても大丈夫なようにしています。

app/views.py
from django.views import View
from .models import Article
from . import forms
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

class ArticleList(View):
  paginate_by = 10

  def get(self, request, **kwargs):
    form = forms.Paginate(request.GET or None)

    if 'paginate_by' in request.GET:
      request.session['paginate_by'] = request.GET['paginate_by']

    if 'paginate_by' in request.session:
      self.paginate_by = request.session['paginate_by']

    queryset = Article.objects.all()
    paginator = Paginator(queryset, self.paginate_by)
    try:
      contents = paginator.page(kwargs['page'])
    except PageNotAnInteger:
      contents = paginator.page(1)
    except EmptyPage:
      contents = paginator.page(paginator.num_pages)
    context = {}
    context['contents'] = contents
    context['form'] = form

    return render(request, 'app/article_list.html', context)

URLs

app/urls.py
from django.urls import path
from . import views

app_name = 'app'

urlpatterns = [
  path('article_list/<int:page>', views.ArticleList.as_view(), name='article_list'),
]

Template

app/aritcle_list.html
  <form name="paginate_form" action="{% url 'main:user_list' 1 %}" method="get">
    {{ form.paginate_by.label }} {{ form.paginate_by }}
  </form>

  <table class="table twitter-user-list">
    <thead>
    <tr>
      <th scope="col">タイトル</th>
      <th scope="col">内容</th>
    </tr>
    </thead>
    <tbody>
    {% for article in contents %}
      <tr>
        <td class="align-middle">{{ article.title }}</td>
        <td class="align-middle">{{ article.content }}</td>
      </tr>
    {% endfor %}
    </tbody>
  </table>
  <nav aria-label="Page navigation">
    <ul class="pagination justify-content-center">
      {% if contents.has_previous %}
        <li class="page-item">
          <a href="{% url 'app:article_list' 1 %}" class="page-link">1</a>
        </li>
        <li class="page-item">
          <a href="{% url 'app:article_list' contents.previous_page_number %}" class="page-link"><</a>
        </li>
      {% else %}
        <li class="page-item disabled">
          <a href="#" class="page-link">1</a>
        </li>
        <li class="page-item disabled">
          <a href="#" class="page-link"><</a>
        </li>
      {% endif %}
      <li class="page-item active">
        <a class="page-link" href="#">{{ contents.number }}</a>
      </li>
      {% if contents.has_next %}
        <li class="page-item">
          <a href="{% url 'app:article_list' contents.next_page_number %}" class="page-link">></a>
        </li>
        <li class="page-item">
          <a href="{% url 'app:article_list' contents.paginator.num_pages %}" class="page-link">{{ contents.paginator.num_pages }}</a>
        </li>
      {% else %}
        <li class="page-item disabled">
          <a href="#" class="page-link">></a>
        </li>
        <li class="page-item disabled">
          <a href="#" class="page-link">{{ contents.paginator.num_pages }}</a>
        </li>
      {% endif %}
    </ul>
  </nav>

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?