Help us understand the problem. What is going on with this article?

[Django] 常時Ajaxで動く検索画面を1時間で作ろう! jQuery Datatables サーバ連携機能の紹介 【サンプルアプリ有り】

More than 1 year has passed since last update.

1.この記事について

この記事は Django Advent Calendar 2018 12月19日の記事です。

たいていのアプリには検索一覧画面が必要ですが、使いやすさのために並べ替えやページ分割機能などを追加していけば当然開発工数がふくらみます。

そこで、この記事ではjQueryプラグイン「DataTables」のサーバ連携機能(Server-Side Processing)を紹介します。検索画面のUIを簡単に実装するDataTablesと、各フレームワーク向けに提供されているサーバ連携機能用ライブラリを組み合わせることで、簡潔なコードで高機能な検索一覧画面を作ることができます。

この記事ではWebアプリケーションフレームワークとしてPythonのDjangoを使った例を紹介しますが、サーバ連携機能用ライブラリはRails、Larabelでも公開されています。おそらく同じ要領で実装可能ですので、是非試してみてください。

  • DataTables サーバ連携機能用ライブラリの一覧
フレームワーク ライブラリ
Django django-datatables-view
Ruby on Rails ajax-datatables-rails
Larabel Laratables

サンプルページ

実際の動作を確認できるサンプルページを用意しました。

バージョン

  • Python 3.7.0
  • Django 2.1.3
  • django-datatables-view 1.17.0
  • django-excel-response 2.0.3
  • jquery.dataTables 1.10.19
  • twitter-bootstrap 4.1.1

2.画面イメージ

実際の動作はサンプルページかサンプルアプリで確認できます。

サンプル1:PC用
localhost_8000_sample01(iPad) (2).png

サンプル2:モバイル用

DataTablesはレスポンシブデザインに対応しています。
幅の制限で表示しきれなくなった情報は詳細行に移動します。「丸に+」のマークをタップすると折りたたまれた詳細行が開きます。

image.png

サンプル3:タスク管理ツール

DataTablesにデータの追加・更新機能を付けました。
入力フォームにはBootstrapのモーダルフォーム、バックエンドにはDjango RestAPI Frameworkを利用しています。

image.png

3.サンプルアプリの使い方

実際に動かして試すことのできるサンプルアプリ(Djangoのプロジェクト)を用意しました(要:Python 3.5以上)。

https://github.com/okoppe8/django-datatables-view-sample

ReadMeの内容に従ってセットアップしてください。venv で仮想環境を作るので本体の環境に影響はありません。

データはこちらのページのものを使わせていただきました。

なおDjangoについての基本的な情報はこちらにまとめたので参考にしてください。

4.DataTablesとサーバ連携機能について

DataTablesはデータグリッドを表示するためのjQueryプラグインです。データソースとして既存のtable、JSONファイル、JSONを提供するWebAPIが使えます。機能や表示オプションが充実している事に加え、jQueryなので容易に扱うことができます。

この手のプラグインには共通の欠点があり、それはデータを一度に読み込む必要があり、扱うデータが千件ちかくなると処理が重くて使い物にならなくなるという点なのですが、DataTablesはその問題についてサーバ連携機能(Server-Side Processing)という解決策を用意しています。

これはDataTablesの仕様に沿ったバックエンド(WebAPI)を用意すると、検索・ソート・ページ分割処理をサーバ側で行われるので、最小限の処理コストで表示が更新されるようになるというものです。これによりデータ件数が多くても気兼ねなくDataTablesが利用できます。

このWebAPIを自前で実装するのは面倒なので、設定より規約(convention over configuration)方式によりORMのモデルからWebAPIを実装するライブラリが有志によって公開されています。このライブラリを利用して短いコードで高機能な検索画面が作成できるというわけです。

5.検索画面の作り方

Djangoでのサーバ連携機能の実装方法を説明します。前提としてモデル・データベース・マスタデータは既に作成済みとします。

バックエンドを作る

まずバックエンドとなるのWebAPIを作ります。Djangoではライブラリ「django-datatables-view」を使って実装します。

django-datatables-view の利用方法は簡単です。まずパッケージをインストールします。

pip install django-datatables-view

次にDjangoのView(一般的なMVCでのControllerに相当)を実装します。

views.py
from django.views import generic
from django_datatables_view.base_datatable_view import BaseDatatableView

from .models import Item


class ItemsJsonView(BaseDatatableView):
    # モデルの指定
    model = Item
    # 表示するフィールドの指定
    columns = ['id', 'pref_name', 'name', 'furigana', 'zipcode', 'address', 'tel', 'code']

    # 検索方法の指定:部分一致
    def get_filter_method(self):
        return super().FILTER_ICONTAINS

Viewはdjango_datatables_viewが提供するClass-Based-Viewの「BaseDatatableView」を継承して作ります。主な設定項目は以下の通りです。

  • model
    • 検索対象のモデルを指定
  • columns
    • 表示させるフィールドを選択
  • def get_filter_method
    • 検索方法。デフォルトは「FILTER_ISTARTSWITH(前方一致)」。「FILTER_ICONTAINS(部分一致)」に変更可。

※ ここからサンプルコード外

  • def get_initial_queryset

    • 初期クエリセットを指定する。たとえば論理削除データは表示しない、管理者以外は自分のデータのみ表示という要件はここで実現可能。
  • def filter_queryset

    • 検索処理をカスタマイズできる。自前で検索フォームを用意して複雑な検索を行うという用途に使う。このメソッドの使い方についてはいつか別の記事を書きたいと思う。
  • def prepare_results

    • 出力する前にデータを加工する。なおフロントエンド部でもデータの加工は可能(renderプロパティ)。

他にもいくつか項目があるので公式サイトで確認してください。
定義ができたらurls.py(ルーティングテーブル)にエンドポイントを登録します。

urls.py
urlpatterns = [
    path('items', views.ItemsJsonView.as_view(), name='ItemsJson'),
]

フロントエンドを作る

バックエンドが完成したらテンプレート(一般的なMVCにおけるViewに相当)を作成します。
HTML上にtableタグを配置し、必要なライブラリをlink・scriptで定義し、JavaScriptで以下のコードを書きます。問題がなければDataTablesにデータが表示されるはずです。

参考:https://datatables.net/examples/server_side/simple.html

$(document).ready(function() {
    var oTable = $('.datatable').dataTable({
        // ...
        "processing": true,
        "serverSide": true,
        "ajax": "items" // 上で作成したエンドポイント
    });
    // ...
});

DataTables 参考リンク

DataTablesには非常に多くの機能があります。基本的な設定方法や応用的な使い方については公式サイトやサンプルコード、以下のリンクで調べていただきたいと思います。

6.レポート機能を自作する

DataTablesには「Buttons」という拡張機能があります。

参考:公式サイトのボタン機能のサンプル

これは選択中のデータをExcel・CSV・PDF・クリップボードにコピー・印刷するためのボタンを追加するという便利な機能です。しかし残念ながらこのサーバ連携機能での動作時には使えません。ページをまたいで選択状態を保存するという機能がないのです。

ですがもともとこの機能は表現面で制約が多く、あらためて考えるとそれほど実用的な機能ではありません。そこで、より自由な表現ができるようにサーバサイド側でレポート機能を実装してみました。

Excel・CSV出力

DjangoでExcelファイルのダウンロードを簡単に実装するなら「django-excel-response」が便利です。

例えばデータを表示するMyListViewがすでにあったとして、同じデータをダウンロードさせるViewのコードは以下の通りです。

views.py
from excel_response import ExcelMixin
class ExcelView(ExcelMixin, MyListView):
   pass

これだけ。非常にシンプルです。

ただ、このままだとExcelの見出し行はフィールド名がそのまま表示されてしまうので、日本語の見出しをつけるには以下のようにコードを追加してください。ファイル名の変更等もできます。設定方法は公式サイトで確認してください。

views.py
class ExcelView(ExcelMixin, MyListView):
    # 見出し行を日本語にする
    def get_queryset(self):
        header = [['id', '県名', '市町村名', 'ふりがな', '郵便番号', '住所', '電話番号', '自治体コード']]
        body = [list(entry.values()) for entry in super().get_queryset().values()]
        return header + body

force_csv = Trueという設定でcsvでの出力にも対応します。このcsvの文字コードはBOM無しutf-8です。直接 Excelで開くと文字化けするので注意してください。

印刷

サンプルアプリの印刷機能はラベルシールのシートへの印刷用です。こういうシートに郵便物に貼るための宛名を印刷するイメージですね。

印刷画面はこちらの記事を参考に作りました。

HTMLで印刷機能を作る場合、Webの技術がそのまま使えます。たとえばバーコードQRコードが簡単に使えるというメリットがあり非常に便利です。

PDF出力(断念)

こちらの記事を参考にPDFファイルの出力を実装しようと思ったのですが、残念ながら私の技術ではどうにも日本語の文字化けが解決できず断念しました。うまく出力できた人がいたらやり方を教えてください m(_ _ )m。

xhtml2pdfを使ったPDFの印刷は可能でした!
結論から言うと、以下のエントリの方法でOKです。

注意してほしいのは、フォントファイルを配置する場所はアプリ内のstaticディレクトリではダメで、ちゃんとsettings.STATIC_ROOTを設定し、対応するディレクトリを作成してそこに配置する必要があります。

ただしxhtml2pdfをある程度試してみましたが、スタイルシートがまともに機能しないためデザイン性のある帳票の作成は断念せざるを得ませんでした。多少の変更でHTMLをPDFに変換できるというイメージは甘かったようです。

もしPDF出力が必要ならWeasyPrintを使う方法もあるようです。こちらはpip外のモジュールを別途OSにインストールする必要がありますが、xhtml2pdfよりもデザイン性の高いものに対応できるようです。

7.データの更新方法

当然、登録画面や更新画面を作ればデータの更新はできますが、Djangoには管理アプリという裏技があります。

これは簡易CMSとして使えるようにDjangoのプロジェクトにはじめから付属しているアプリで、定義したモデルの登録・更新・削除が優れたUIで利用できます。

この機能は以下の手順で有効になりますので、Djangoを使ったことが無い方は是非試してみてください。

1. ターミナルより以下のコマンドを実行し管理者のIDとPassを入力する。

  • windows
env\Scripts\activate
manage.py createsuperuser
  • MacOS
source env/bin/activate
python manage.py createsuperuser

E-mailの設定は未入力でよい。

2. ブラウザで「localhost:8000/admin」にアクセスし作ったID/Passを使う。

8.DjangoでWebアプリをカジュアルに使おう

サンプルアプリのように、Djangoのプロジェクトはこのような形で簡単に他人に実行してもらうことができます。これはPythonの標準モジュールの中にhttpサービスがもともと組み込まれていることと、Pythonは実行環境を容易に分離できるということのおかげです。

この特長を生かしてWebアプリを一般ユーザーにもっとカジュアルに使ってもらうことはできないかということを考えています。

サンプルアプリでセットアップのコマンドをいくつか実行しましたが、これはまとめてスクリプト化できます。さらにhttpの起動とブラウザの立ち上げもスクリプト化し、適当なショートカットを作ってアイコンを変えてしまえば、デスクトップアプリと同じように使ってもらえるのでは?と思うのです。

個人的に興味があるのはMicrosoft AccessFileMakerが対象とする業務をこの方法でカバーできないだろうか、ということです。

今回紹介した方法のようにJavascriptのプラグインやフレームワークを活用すれば開発効率はAccessやFileMakerに劣りませんし、はるかに自由なコーディングが可能です。Gitで管理できるというメリットも生まれますし、当然ライセンス料が不要・OSに関係なく動くといったメリットは一般層にも強くアピールできると思います。

予算不足でライセンスがまとも買えないという現場が多い中、なんとか業務改善を進める方法として提案させていただきます。ぜひ皆さんの意見を聞かせてください。

okoppe8
札幌でシステムエンジニアをしています。 「Djangoで業務システム作る時に必要な機能をあらかじめ用意する」というテーマでやってます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした