ng-admin + Django REST framework ですぐ作れる管理ツール


Django REST framework と ng-admin で管理ツールを作ってみた

REST API + Static web で管理ツールを実現する方法として ng-adminDjango REST framework を使ってみました。
本記事は Python と Javascript の使用経験がある読者を対象としています。
本記事のソースコードは以下のリポジトリに公開しています。

ライブラリ紹介

  • Django REST framework: REST API を簡単に作れる Python のウェブフレームワーク。名前のとおり Django がベースになっている。
  • ng-admin: 管理ツールに特化した Javascript のクライアントライブラリ。こちらは Angularjs に依存している。

サーバ構成

図に書くまでもありませんが、以下のようなサーバ構成になります。

---------------------------
Static Web (127.0.0.1:8080) // ng-admin
---------------------------
           |
---------------------------
Web API    (127.0.0.1:8000) // REST framework
---------------------------

環境構築

Pyenv (pyenv-virtualenv) で Python 3.5.2 がインストールされているものとします。
また npm も導入済みであるとします。
ちなみに筆者の環境は macOS El Capitan です。

Django REST framework

Django REST framework をインストールします。
今回は筆者が用意したリポジトリを使うこととします。

  1. リポジトリの取得
    git clone https://github.com/algas/rest-admin-example.git
  2. virtualenv 環境の作成
    cd rest-admin-example && pyenv virtualenv 3.5.2 rest-admin-example
  3. virtualenv の activate
    pyenv activate rest-admin-example
  4. 依存ライブラリのインストール
    pip install -U pip && pip install -r requirements.txt
  5. database migration
    cd tutorial && python manage.py migrate
  6. スーパユーザの新規作成
    python manage.py createsuperuser
    ガイドにしたがってユーザ名、Eメールアドレス、パスワードを入力します。

環境を自前で1から作成したい方は quickstart tutorial を参考にしてください。
一部の不具合修正を除けばこのチュートリアルと同じ内容を実行しています。

  • Django-1.10
  • djangorestframework-3.4.4

ng-admin

  1. カレントディレクトリの移動
    cd ../js
  2. 依存ライブラリのインストール
    npm install ng-admin --save

上記の npm install は必ず js ディレクトリで実行するようにしてください。
作成される node_modules へのパスに依存しているからです。

  • ng-admin-1.0.0-alpha2

サーバの起動

Django サーバと (Static) Web サーバを別々に立ち上げるために2画面のターミナルを用意します。

Django REST framework

  1. カレントディレクトリの移動
    cd /path/to/rest-admin-example/tutorial
  2. サーバの起動
    python manage.py runserver
  3. 動作確認
    下記にブラウザでアクセスします。
    http://127.0.0.1:8000/

ng-admin

ここでは python 3 標準のWebサーバ(http.server)を使います。nginx など他の web サーバでも問題ありません。

  1. カレントディレクトリの移動
    cd /path/to/rest-admin-example/js
  2. サーバの起動
    python -m http.server 8080
  3. 動作確認
    下記にブラウザでアクセスします。
    http://127.0.0.1:8000/

コード解説

API

users と groups という2つのAPI群が定義されています。
各モデルの定義は以下のとおりです。

User: url, username, email, groups
Group: url, name

User は任意の数のグループに所属できます。
url は作成された API 要素へのリンクを表します。
http://127.0.0.1:8000/users/1/
http://127.0.0.1:8000/groups/1/

管理ページ

管理ページでは User, Group の一覧の表示と新規要素の作成機能を実装しました。
この機能は index.html と admin.js の2つのファイルで実現されています。

index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Rest Admin Page</title>
        <link rel="stylesheet" href="node_modules/ng-admin/build/ng-admin.min.css">
    </head>
    <body ng-app="restAdmin">
        <div ui-view></div>
        <script src="node_modules/ng-admin/build/ng-admin.min.js" type="text/javascript"></script>
        <script src="admin.js" type="text/javascript"></script>
    </body>
</html>

上記は node_modules にインストールされた ng-admin の js, css に加えて、下記の admin.js を参照しています。

admin.js
var restAdmin = angular.module('restAdmin', ['ng-admin']);
restAdmin.config(['NgAdminConfigurationProvider', function (nga) {
    var admin = nga.application('Rest Admin')
      .baseApiUrl('http://127.0.0.1:8000/');

    var group = nga.entity('groups').identifier(nga.field('url')).url(function(entityName, viewType, identifierValue, identifierName) {
        return 'groups/';
    });
    var groupFields = [
        nga.field('url'),
        nga.field('name')
    ]
    group.listView().fields(groupFields);
    group.creationView().fields(groupFields);
    admin.addEntity(group);

    var user = nga.entity('users').identifier(nga.field('url')).url(function(entityName, viewType, identifierValue, identifierName) {
        return 'users/';
    });
    var userFields = [
        nga.field('url'),
        nga.field('username'),
        nga.field('email'),
        nga.field('groups', 'json'),
    ]
    user.listView().fields(userFields);
    user.creationView().fields(userFields);
    admin.addEntity(user);

    nga.configure(admin);
}]);

まず http://127.0.0.1:8000/ を baseApiUrl として定義しています。
次は Entity として users, groups を定義です。
ng-admin のデフォルト仕様では URI の末尾にスラッシュ(/)が入らないことを想定しています。
しかし、django framework の仕様で URI の末尾にスラッシュ(/)が必ず入るので、この差異を吸収するために url function を定義しています。
users, groups のそれぞれで listView と creationView を定義しています。
User における groups の要素は、Array で定義されるので、 ng-admin の Field Type として json を指定しています。

注意点

  • CORS の設定
    通常の設定では Cross-Origin Resource Sharing の問題で API から ng-admin に JSON を渡せません。 django_cors_middleware を使うことでこの問題を回避しています。 settings.py に設定をしているので、筆者のリポジトリを参照する場合には特に対処は不要です。
  • 依存性解決
    上記のライブラリの fork 元が更新されておらず Django-1.10 に対応していなかったので、Pull Req. をして来たユーザのブランチを参照することで解決しています。 これも requirements.txt に記載しているので問題回避できるはずです。

雑感

Django REST framework 自体が Web UI を提供しているので、 ng-admin と組み合わせる利点が見えにくいかもしれません。
Django REST framework は単体で使っても便利です。
ng-admin は当然のことながら、その他の Web API と連携させることもできます。