django_datatables_viewで1ページ100件超えが表示できない不具合の対処法

はじめに

Django で datatables のサーバー連携を使用できる django_datatables_view で、1 ページあたり 100 件を超えるレコードがすべて表示できない不具合の対処法を紹介します。とてもわかりにくい不具合になっており、目視だと気が付かない可能性があります。

django_datatables_view について

django_datatables_view とは、datatables のサーバー連携を使用できる Django のクラスベースビューです。
datatables とは絞り込み・ソートなど多機能なテーブルをかんたんに実装できる jQuery プラグインです。
Django の管理画面よりもカスタマイズ豊富な上に、ほとんどプログラムを書くことなく、(デザイン, フロントエンド, バックエンドも)何も考えずにデータベース内容を一覧に表示できます。
django-datatables-viewを使用しているテーブルのスクリーンショット
今回のユースケースでは、下記のプログラムをお借りしました。ありがとうございます。
okoppe8/django-datatables-view-sample - GitHub
https://github.com/okoppe8/django-datatables-view-sample

1 ページあたり 100 件超えにするとレコード数がおかしい

datatables の lengthMenu を変更すると、1 ページあたりの表示件数を柔軟に変更できます。
10 件でも、1 件でも、2^53-1 件でも設定できます。
datatables で件数が変更できる部分のスクリーンショット
lengthMenu - datatables
https://datatables.net/reference/option/lengthMenu
ある案件で、最大「500 件」の選択ができるように設定していました。500 件にすると下記のようになります。
datatables で表示件数500件にしたスクリーンショット。しかし、1件目から100件目しか表示されていない。
一見すると、正しく表示できていそうに見えますが、皆さん、このスクショにある「不具合」を1点見つけてくださいませ。
いくら北海道がデカいとはいえ、地方自治体が 500 もあるわけがないのです。(ちなみに 179 あるらしいです)
試しに次のページに行ってみましょう。
datatables の表示件数500件にして2ページ目に行ったスクリーンショット。501件目から表示される。
群馬県に突入しています。つまり、「1 ~ 500 件表示」となっていながら、500 件のレコードが表示できていないのです。実際には 100 件しか表示されていません。
その案件ではデフォルトは 100 件にしており、テストもそれで通っていたので目視でしか確認しておらず発見できていませんでした。気づきにくい重大な不具合を生んでしまったのです。

django_datatables_view の返却レコード数上限

django_datatables_view には返却レコード数上限の設定( max_display_length )があります。README.md には下記の記述があります。
set max limit of records returned, this is used to protect our site if someone tries to attack our site
and make it return huge amount of data max_display_length = 500
django-datatables-view · PyPI
https://pypi.org/project/django-datatables-view/
リクエスト自体は単純な GET のため、やろうと思えば大量のデータを取得する攻撃ができてしまう意図から設定されている設定です。こちらのデフォルト値は 100 になっています。

返却レコード数上限を変更する

正常に動作させるためには返却レコード数上限を変更する必要があります。lengthMenu の最大値を設定しましょう。
from django_datatables_view.base_datatable_view import BaseDatatableView

class ExampleList(BaseDatatableView):
  model = MyModel
  columns = ['id', 'name', 'dateAt', 'updatedAt']
  max_display_length = 500
再度実行してみましょう。
表示件数を500件にしたdatatablesのスクリーンショット。1-500件目が正しく表示されている。
無事群馬県までの 500 件が表示されるようになりました。

基本設定のクラス化

複数のページで使用している場合、設定漏れがあると不具合の原因となるので、基本設定は基底クラス化してしまいましょう。下記のように作ります。
from django_datatables_view.base_datatable_view import BaseDatatableView

class ExtendDatatableView(BaseDatatableView):
  # フロントdatatablesのlengthMenu最大値と揃えること
  max_display_length = 500
from app.library.extend_datatable_view import ExtendDatatableView

class ExampleList(ExtendDatatableView):
  model = MyModel
  columns = ['id', 'name', 'dateAt', 'updatedAt']

まとめ(反省)

  • ライブラリの README はちゃんと読もう
  • 目視で不具合に気がつけるようにテストデータは分かりやすくしよう
  • テストは条件変更した場合の挙動も確認しよう

ホームプロフィール外部リンクのため、別ウインドウで開きますプライバシーポリシー

© 2023 Oishi Takanori / Made with Gatsby.js