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

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

django_datatables_viewについて

django_datatables_viewとは、datatablesのサーバー連携を使用できるDjangoのクラスベースビューです。
datatablesとは絞り込み・ソートなど多機能なテーブルをかんたんに実装できるjQueryプラグインです(今どきjQuery?って声が聞こえてきそうですが、どんなライブラリも適材適所ですよ)。

控えめに言って、ハイパー楽で便利です。Djangoの管理画面よりもカスタマイズ豊富な上に、ほとんどプログラムを書くことなく、(デザインもフロントエンドもバックエンドも)何も考えずにデータベース内容を一覧に表示することができます。

django-datatables-viewの使用例

今回のユースケースでは、下記のプログラムをお借りしました。ありがとうございます。

GitHub - okoppe8/django-datatables-view-sample
Contribute to okoppe8/django-datatables-view-sample development by creating an account on GitHub.

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

datatablesの lengthMenu を変更すると、1ページあたりの表示件数を柔軟に変更することができます。

10件でも、1件でも、253-1件でも設定できます。

datatabels lengthMenu

lengthMenu

ある案件で、最大「500件」の選択ができるように設定していました。500件にすると下記のようになります。

500件にしたときの表示

一見すると、正しく表示できていそうに見えますが、皆さん、このスクショにある「不具合」を1点見つけてくださいませ。

・・・

いくら北海道がデカいとはいえ、地方自治体が500もあるわけがないのです。(ちなみに179あるらしいです…すごい)

試しに次のページに行ってみましょう。

次のページは群馬県

群馬県に突入しています。つまり、「1~500件表示」となっていながら、500件のレコードが表示できていないのです。実際には100件しか表示されていません。

その案件ではデフォルトは100件にしており、E2Eテストもそれで通っていたので目視でしか確認しておらず発見できていませんでした。気づきにくい重大な不具合を生んでしまったのです。

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
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件にしたときの表示

無事群馬県までの500件が表示されるようになりました。

基本設定のクラス化

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

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

- class ExampleList(BaseDatatableView):
+ class ExampleList(ExtendDatatableView):
model = MyModel
columns = ['id', 'name', 'createdAt', 'updatedAt']
- max_display_length = 500

まとめ(反省)

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

コメント