revision-up-to: | 17812 (1.4) |
---|
このチュートリアルは チュートリアルその 1 の続き です。ここでは、引続き Web 投票アプリケーションの開発を例にして、Django が 自動生成する管理サイト (admin) を中心に解説します。
設計哲学
コンテンツの追加や変更、削除を行うためのスタッフや顧客向けの管理サイト 構築は、創造性の欠けた退屈なものです。そこで、 Django ではモデルを管 理するためのインタフェース生成を完全に自動化しています。
Django はニュースルーム環境で開発されました。ニュースルーム環境では、 「コンテンツの作成者 (content publisher) 用」と「公開用 (public) 」サイ トをきわめて明確に区別しています。サイト管理者は新たな話題やイベント、 スポーツのスコアなどの入力に使い、コンテンツは公開用サイト上で表示され ます。 Django は、サイト管理者向けの一元化されたコンテンツ編集インタフェー スの提供という問題を解決しているのです。
admin は一般のサイト訪問者に使ってもらうためのものではなく、サイト管理 者のためのものです。
デフォルトでは、 Django の管理サイトは無効化されていて、自分で選択して有効 にせねばなりません。 admin を有効にするには、以下の 3 つの作業が必要です:
INSTALLED_APPS
設定の "django.contrib.admin"
をコメント
アウトを解除します。
python manage.py syncdb
を実行します。新たなアプリケーションを
INSTALLED_APPS
に追加したので、データベースを更新せねばな
りません。
mysite/urls.py
ファイルを編集し、 admin に関連する3行のコメントアウト
を解除します。このファイルは URLconf といいます。 URLconf についてはチュー
トリアルの次の部で解説します。今はただ、この設定が URL をアプリケーション
に対応づけていることだけを覚えておきましょう。最終的に、 urls.py
は
以下のようになるはずです:
from django.conf.urls import patterns, include, url # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', '{{ project_name }}.views.home', name='home'), # url(r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)), )
(太字の行はコメントを外した部分です)
開発用サーバを起動して、管理サイトを探検してみましょう。
チュートリアルその 1 で、開発サーバを以下のように起動したのを思い出してくだ さい:
python manage.py runserver
次はブラウザを起動して、ローカルドメインの “/admin/” 、つまり http://127.0.0.1:8000/admin/ にアクセスします。以下のような admin のログイ ン画面が表示されるはずです:
自分の画面と違う場合
もしこの時点で、上のログイン画面の代わりに以下のようなエラーの画面が 表示された場合は:
ImportError at /admin/
cannot import name patterns
...
おそらくこのチュートリアルのバージョンとは違う Django のバージョンを 使用していることでしょう。古いチュートリアルを参照するか、新しいバー ジョンの Django を入手してください。
さあログインしてみましょう。(チュートリアルその 1 で、スーパユーザのアカウ ントを作成したはずです。覚えていますか?) ログインしたら、管理サイトのインデ クスページが表示されるはずです:
「グループ (Groups)」や「ユーザ (Users)」、「サイト (Sites)」といった編集 可能なコンテンツが表示されるはずです。これらはデフォルトで Django に付属し ているコアの機能です。
ところで、 polls アプリケーションはどこにあるんでしょう? admin のインデ クスページを見ても表示されていませんね。
実は、まだ一つやるべきことが残っていました。 admin に Poll
モデルがイ
ンタフェースを持つことを教える必要があるのです。 polls
ディレクトリに
admin.py
ファイルを追加して、以下のように編集してください:
from polls.models import Poll
from django.contrib import admin
admin.site.register(Poll)
admin のページをリロードして、どんな変化が起きたか見てみましょう。通常、 開発サーバはプロジェクトを自動的にリロードしてくれるので、コードに加えた変 更はただちにブラウザで確認できます。
Poll
モデルを登録したので、 Django は Poll
を管理サイトに表示するよ
うになりました:
「Polls」 をクリックしてみてください。 チェンジリスト (change list) のペー
ジに入ります。このページはデータベース上の全ての Poll
オブジェクトを表
示していて、変更したいオブジェクトを選択できます。前のチュートリアルで作成
した 「What’s up」という Poll
オブジェクトがありますね。
「What’s up?」をクリックして編集してみましょう:
以下の点に注意してください:
DateTimeField
,
CharField
などの) 適切な HTML 入力ウィジェッ
トが対応しています。各タイプのフィールドには、 Django 管理サイトでデー
タを表示する方法が定義されています。DateTimeField
には JavaScript のショートカッ
トがついています。日付 (Date) のカラムには「今日 (Today)」へのショート
カットと、カレンダーのポップアップボタンがあります。時刻 (Time) のカラ
ムには「現在 (Now)」へのショートカットと、よく入力される時間のリストを
表示するポップアップボタンがあります。ページの末尾の部分には操作ボタンがいくつか表示されています:
もし「Date published」の値がチュートリアル 1 で作成した時間と違う場合は、
TIME_SONE
に現在のタイムゾーンの設定をし忘れた可能性があります。
変更し、リロードして正しい値が表示されるか確認してください。
「今日」や「現在」ショートカットをクリックして、「Date published」を変更し てみましょう。変更したら、「保存して編集を続ける」を押します。次に、右上に ある「履歴 (History)」をクリックしてみましょう。ユーザが管理サイト上でオブ ジェクトに対して行った全ての変更履歴を、変更時刻と変更を行ったユーザの名前 つきでリストにしたページを表示します:
しばらく操作してみましょう。これだけの機能をコードを書かずに実現したこ
とに驚くはずです。 admin.site.register(Poll)
の呼び出しによって、
Django はオブジェクトの表示方法を「推測」し、管理サイトでモデルの編集を行え
るようにします。管理サイトの表示や挙動を少し変えたい場合には、モデルを登録
するときにオプションを指定します。
試しに、編集フォームでのフィールドの並び順を並べ替えてみましょう。
admin.site.register(Poll)
の行を以下のように置き換えてみてください:
class PollAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question']
admin.site.register(Poll, PollAdmin)
このように、 admin のオプションを変更したいときには、モデルごとに admin
オブジェクトを生成して、 admin.site.register()
の 2 番目の引数に渡すと
いうパターンを使ってください。
上の例では、「Publication date」フィールドの表示位置を「Question」フィール ドよりも前に変更しています。
二つしかフィールドがないので、あまりぱっとした変化ではありませんね。しかし admin フォームで何ダースものフィールドを操作するような場合には、直感的なフィー ルドの並び順というものはユーザビリティ上重要な要素です。
同じく何ダースもフィールドがある場合、フォームを複数のフィールドセットに分 割したいこともあるでしょう:
class PollAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Poll, PollAdmin)
fieldsets
の各タプルの先頭の要素はフィールドセットのタイトルです。
フォームは以下のように表示されます:
各フィールドセットには任意の HTML クラスを指定できます。 Django では
"collapse"
というクラスを提供していますが、このクラスを指定すると、フィー
ルドセットは最初折り畳まれた状態で表示されます。これは普段は使わないフィー
ルドがたくさんあるようなフォームを使っている場合に便利です:
class PollAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
OK、 Poll の管理サイトページはできました。しかし Poll
は複数の Choice
を持つのに、管理サイトページには表示されていませんね。
今のところは。
Poll
と同様、以下のようにして Choice
モデルを管理サイトに登録するというものです:
from polls.models import Choice
admin.site.register(Choice)
これで、 Django の管理サイト上で「Choice」 を選べます。「Choice の追加」フォーム は以下のようになります:
このフォームでは「Poll」フィールドは選択ボックスで、データベース上の全ての
Poll オブジェクトを選ます。 Django は ForeignKey
を表示する時には <select>
ボックスを使わねばならないということを知って
いるのです。今の時点では、 Poll はデータベース上に一つしかないはずですね。
Poll フィールドの隣に「もう一つ追加 (Add Another)」リンクがあるのに注意して ください。 ForeignKey の関係にあるオブジェクトなら、何もしなくてもこのリン クが表示されます。「もう一つ追加」をクリックすると、「Poll を追加 (Add Poll)」というポップアップウィンドウを表示します。このウィンドウで Poll を追 加して「保存」を押すと、 Django は Poll をデータベースに保存して、もとの 「Choice の追加」フォームに選択済みの項目として動的に追加します。
しかし、この方法は Choice オブジェクトをシステムに追加するには効率的ではあ りません。むしろ、 Poll オブジェクトを追加する時に Choice をひと揃い追加出 来た方が便利ですよね。そうしてみましょう。
Choice モデルに対する register()
を削除して、 Poll
を登録する部分を
以下のように書き換えてください:
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
class PollAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
admin.site.register(Poll, PollAdmin)
この行は Django に対して、「Choice オブジェクトは Poll の管理ページから編集 する。デフォルトでは、 3 つの Choice を表示するのに十分なフィールドを用意す ること」と指示しています。
「Poll を追加」ページをロードして、どんな表示になったか見てみましょう。開発 サーバをリスタートする必要があるかもしれません:
変わった点をみてみましょう。リレーション相手である Choice を表示するために
3 つのスロットがあります (extra
に指定した数ですね)。また、作成済みのオ
ブジェクトを「編集する」ページに行けば、いつでも 3 つ余分のスロットが表示さ
れるはずです。
さて、このコードにはちょっと問題があります。というのも、 Choice オブジェク
トを入力するためのフィールドを全部表示しようとすると、相当な広さのスクリー
ンが必要だからです。そこで、 Django にはテーブルを使ってインラインでリレー
ション相手のオブジェクトを表示するもう一つの方法があります。以下のように、
ChoiceInline
の宣言を変更してください:
class ChoiceInline(admin.TabularInline):
#...
StackedInline
に変わって TabularInline
を使うと、
リレーション相手のオブジェクトはよりコンパクトなテーブル形式で表示されます:
さあ、これで Poll の管理ページはだいぶよくなってきました。今度は「チェンジ リスト」ページをすこしいじりましょう。チェンジリストは、システム上の全ての Poll を表示するページです。
作業前のチェンジリストのページは以下のように表示されています:
デフォルトでは、 Django はオブジェクトの str()
を表示しますが、各フィー
ルドの値も表示されていると便利でしょう。表示させるには list_display
オ
プションを使います。 このオプションには、カラム表示したいフィールドの名前を
タプルにして指定します:
class PollAdmin(admin.ModelAdmin):
# ...
list_display = ('question', 'pub_date')
おまけとして、チュートリアル 1 で定義したカスタムメソッド
was_published_recently
も追加してみましょう:
class PollAdmin(admin.ModelAdmin):
# ...
list_display = ('question', 'pub_date', 'was_published_recently')
これで、 Poll のチェンジリストのページは以下のようになります:
カラムのヘッダをクリックすると、カラムの値に応じてエントリを並べ換えできま
す。ただし was_published_recently
ヘッダは例外で、これはメソッドの戻り値を
使った並べ換えをサポートしていないからです。 was_published_recently
のカラ
ムヘッダのデフォルト値がメソッドの名前になっている (アンダースコアは空白に
置き換わっている)こと、各行が戻り値の文字列となっていることにも注意して下さい。
以下の属性を (models.py
の中の) メソッドに与えることで、これを改良出来ま
す:
class Poll(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
admin.py ファイルを編集し、もう一点、 Poll のチェンジリストを改良して、フィル
タをを加えます。以下の行を PollAdmin
の中に入れます:
list_filter = ['pub_date']
これで、「フィルタ (Filter)」サイドバーができ、チェンジリストを pub_date
フィールドの値に従ってフィルタできるようになります:
表示されるフィルタのタイプは、フィルタに使うフィールドのタイプによって変わ
ります。 pub_date
は DateTimeField
なので、 Django はデフォルトのフィルタのオプションとして
「すべての日 (Any date)」、「今日 (Today)」、「過去 7 日間 (Past 7 days)」、
「今月 (This month)」そして「今年 (This year)」を与えればよいと考えます。
細工は隆々ですね。こんどは検索機能を追加してみましょう:
search_fields = ['question']
これで変更リストの上部に検索ボックスが表示されます。ユーザが検索語を入力
すると、 Django は question
フィールドを検索します。フィールドはいくつ
でも使えますが、舞台裏では LIKE
クエリを使っているので、データベースに
負荷をかけないためには常識的な検索語を指定しましょう。
最後に、 Poll オブジェクトには日付データがあるので、日付を使って絞り込める と便利なはずです。以下の一行を追加しましょう:
date_hierarchy = 'pub_date'
これで、日付を使った階層的なナビゲーションが変更リストページの上部に追加さ れます。トップレベルでは、エントリのある年を表示します。その下は月になって いて、最後は日ごとにエントリを表示します。
さて、変更リストには何もしなくてもページ分割機能がある、ということをここで お知らせしておいた方がよいでしょう。デフォルトではページあたり 100 個の要素 を表示します。ページ分割、検索ボックス、フィルタ、日付による階層化、カラム ヘッダを使った並べ換えといった変更リストの機能は、すべてが協調して思いのま まに動作するのです。
管理サイトの上部には「Django 管理 (Django adminstration)」と表示されてい ますが、これはいささか滑稽ですね。これは単なるプレースホルダテキストにすぎ ません。
変更するのは簡単で、 Django のテンプレートシステムを使います。 Django の 管理サイトは、それ自身 Django で作られているので、インタフェースは Django のテンプレートシステムを使っているのです。
設定ファイル (mysite/settings.py
でしたよね) を開いて、
TEMPLATE_DIRS
という設定を探して下さい。
TEMPLATE_DIRS
はファイルシステム上のディレクトリ名からなるタプル
で、 Django テンプレートをロードするときに探す場所を指定します。つまり検索
パスです。
デフォルトでは、 TEMPLATE_DIRS
には何も指定されていません。一行
追加して、Django に自作テンプレートの置き場所を教えましょう:
TEMPLATE_DIRS = (
'/home/my_username/mytemplates', # 自分の環境に合わせて変更してください。
)
Django のソースコードの中にある admin アプリケーションのデフォルトのテンプ
レート置場 (django/contrib/admin/templates
) から、
admin/base_site.html
というテンプレートをコピーして、
TEMPLATE_DIRS
上の admin
というディレクトリ下に置きます。例え
ば、 TEMPLATE_DIRS
に "/home/my_username/mytemplates"
と設定
していれば、 django/contrib/admin/templates/admin/base_site.html
を
/home/my_username/mytemplates/admin/base_site.html
にコピーします。
admin
というサブディレクトリを作るのを忘れないようにして下さい。
ファイルを編集して、 Django と書かれた部分を自分のサイトに合わせて変更して ください。
テンプレートファイルは、 {% block branding %}
や {{ title }}
といっ
たテキストを多く含みます。 {%
と {{
タグは Django のテンプレート言語
のうちの一つです。 Django が admin/base_site.html
を読み込んだ時、この
テンプレート言語が評価され、最終的な HTML ページが作られます。今の時点でテ
ンプレートについて理解できなくても心配しないでください。テンプレート言語に
ついてはチュートリアルその 3 で詳しく掘り下げていきます。
admin アプリケーションのデフォルトのテンプレートはどれもオーバライド可能で
す。テンプレートをオーバライドするには、 base_site.html
と同じ、つまり
デフォルトのディレクトリからカスタムディレクトリにコピーして編集するという
手順をとってください。
賢明な読者はこう疑問に思うでしょう:「 TEMPLATE_DIRS
はデフォルト
で何も指定していないのに、 Django はどうしてデフォルトのテンプレートを捜し
当てられるのだろう?」答えは、「デフォルトでは、 Django はテンプレートが見
つからない場合、自動的に各アプリケーションパッケージの templates/
サブ
ディレクトリ下を探すようフォールバックるようになっている」です。詳しくは
テンプレートローダタイプの解説 を参照してください。
もしかすると、同じようにして Django admin サイトのインデクスページのルック & フィールをカスタマイズしたくなるかもしれませんね。
デフォルトでは、インデクスページは INSTALLED_APPS
設定に登録され
ていて、 admin アプリケーションに登録されている全てのアプリケーションをアル
ファベット順に表示します。レイアウトはどのようにも変更できます。なんにせよ、
インデクスページというものは admin で最も重要なページであり、簡単に使えなけ
ればならないはずです。
カスタマイズすべきテンプレートは admin/index.html
です (前節の
admin/base_site.html
の場合と同じように、デフォルトのディレクトリからカ
スタムテンプレート置場のディレクトリにコピーしてください)。ファイルを開くと、
app_list
というテンプレート変数が見つかるはずです。この変数に、インス
トール済みの全てのアプリケーションが入っています。この変数の代りに、特定の
オブジェクトごとに admin ページのリンクをハードコードすれば、自分の思い通り
に変更できます。繰り返しますが、もしテンプレート言語について理解できなくて
も心配しないで下さい。チュートリアルその 3 でテンプレート言語について扱って
いきます。
admin サイトを使いこなせるようになったら、 チュートリアルその 3 に進んで、 poll アプリケーショ ンの公開用ビュー作成にとりかかりましょう。
Oct 26, 2017