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

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

django_datatables_viewについて

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

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

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

django_datatables_viewの返却レコード数上限

django_datatables_viewには返却レコード数上限の設定( max_display_length )があります。README.mdには下記の記述があります。
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', 'createdAt', 'updatedAt']  
  max_display_length = 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', 'createdAt', 'updatedAt']

まとめ(反省)

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

@bicstone

大石貴則 (Ōishi Takanori) と申します。 Webエンジニア / セキュリティスペシャリスト / 機械エンジニア です。 プロダクトに幅広く携わり、相互成長し続けられるエンジニアを目指しています。

GitHubLinkedIn