revision-up-to: | 11321 (1.1) unfinished |
---|
Django の最も強力な機能の一つに、自動生成される admin インタフェースがあり ます。 admin はモデルのメタデータを読み込んで、強力で実運用に耐えるインタ フェースを生成し、コンテンツの製作者がすぐにサイトにコンテンツを投入できる ようにします。このドキュメントでは、 Django の admin インタフェースを有効に したり、カスタマイズしたりする方法を解説します。
注意
admin サイトは Django 0.96 から大幅にリファクタされました。このドキュメ ントでは、よりカスタマイズ機能の充実した新しい admin サイトについて解説 しています。この admin サイトの仕様は、 Django の開発をよく追いかけてい る人なら、一度は “newforms-admin” という名前で耳にしたことがあるはずで す。
Django admin サイトは、以下の 5 つのステップを通して有効化します:
django.contrib.admin
をINSTALLED_APPS
に追加します。- admin インタフェースでの編集を可能にするモデルを決めます。
- 2 で決めたモデルに対して、必要なら
ModelAdmin
クラスを定義します。ModelAdmin
はモデルごとにカスタマイズした admin の機能やオプショ ンをカプセル化しています。AdminSite
をインスタンス化して、モデルやModelAdmin
クラスを 指定します。AdminSite
インスタンスを URLconf にフックします。
See also
For information about serving the media files (images, JavaScript, and CSS) associated with the admin in production, see serving-media-files.
ModelAdmin
オブジェクト¶ModelAdmin
¶ModelAdmin
クラスは、 admin インタフェース上のモデルを表現しています。
このクラスは、アプリケーションの admin.py
という名前のファイルに保存し
ます。 ModelAdmin
の簡単な例を以下に示します:
from django.contrib import admin
from myproject.myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
Do you need a ModelAdmin
object at all?
In the preceding example, the ModelAdmin
class doesn’t define any
custom values (yet). As a result, the default admin interface will be
provided. If you are happy with the default admin interface, you don’t
need to define a ModelAdmin
object at all – you can register the
model class without providing a ModelAdmin
description. The
preceding example could be simplified to:
from django.contrib import admin
from myproject.myapp.models import Author
admin.site.register(Author)
ModelAdmin
のオプション¶ModelAdmin
はとてもフレキシブルなクラスです。このクラスには、 admin イ
ンタフェースをカスタマイズするためのオプションがいくつもあります。オプショ
ンは、全て、 ModelAdmin
のサブクラスで以下のように指定します:
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'
ModelAdmin.
date_hierarchy
¶date_hierarchy
をモデルの DateField
や DateTimeField
に指定する
と、変更リストのページに、指定フィールドの日付を使って日付ベースで絞り込み
できるナビゲーションが組み込まれます。
例:
date_hierarchy = 'pub_date'
ModelAdmin.
form
¶デフォルトの設定では、モデルに対して ModelForm
が動的に生成され、追加/
変更ページでフォームを生成するときに使われます。 form
を独自の
ModelForm
と置き換えれば、追加/変更ページのふるまいを変更できます。
詳しくは、 admin にカスタムのバリデーションを追加する を参照してください。
ModelAdmin.
fieldsets
¶admin の「追加 (add)」および「変更 (change)」ページのレイアウトを制御するに
は、 fieldsets
を使います。
fieldsets
は 2 要素のタプルのリストです。各タプルは admin フォームペー
ジ上の <fieldset>
を表します (<fieldset>
はいわばフォームの「セクショ
ン」です)。
フィールドセットは (name, field_options)
の形式をとります。 name
はフィールドセットの名前を表す文字列で、 field_options
はフィールドセッ
ト内で表示したいフィールドの情報を入れた辞書です。この情報の中に、表示した
いフィールドのリストも指定します。
django.contrib.flatpages.FlatPage
モデルから抜き出した例を示します:
class FlatPageAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('url', 'title', 'content', 'sites')
}),
('Advanced options', {
'classes': ('collapse',),
'fields': ('enable_comments', 'registration_required', 'template_name')
}),
)
このフィールドセットによって、 admin のページは以下のようになります:
fieldsets
を指定しない場合、 Django は AutoField
でなく、かつ
editable=True
であるようなフィールドを、モデルに定義した順番に個別のフィー
ルドセットとして表示します。
field_options
辞書には以下のようなキーを指定できます:
fields
フィールドセット内に表示するフィールド名からなるタプルです。 必須のキーです。使い方:
{ 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), }同じ行に複数のフィールドを表示したい場合、それらのフィールドをタプ ルでラップして入れます。下の例では、
first_name
とlast_name
が同じ行に表示されます:{ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), }
classes
フィールドセットに適用される追加の CSS クラス名です。
使い方:
{ 'classes': ['wide', 'extrapretty'], }admin サイトのデフォルトのスタイルシートで定義されている便利なクラ スとして
collapse
とwide
があります。collapse
スタイ ルのフィールドセットは、 admin ページでは最初折り畳まれ (collapse) ており、小さな”クリックして展開 (click to expand)” リンクに置き換わっ ています。wide
スタイルのフィールドセットには水平方向に追加のス ペースが加わります。
description
各フィールドセットの先頭の、ヘッダのすぐ下に表示する追加の文字列で、 オプションです。
この文字列は admin 上で HTML エスケープ されません 。そのため、必 要ならそのまま HTML を入れられます。また、 HTML 固有の文字をエスケー プしたければ、
django.utils.html.escape()
を使ってください。
ModelAdmin.
fields
¶レイアウトを気にせず、単にモデルの一部のフィールドだけをフォームに表示した
いだけの場合に、 fieldsets
の代わりに使ってください。例えば、
django.contrib.flatpages.FlatPage
モデルの admin フォームの簡単なバージョ
ンを以下のように定義できます:
class FlatPageAdmin(admin.ModelAdmin):
fields = ('url', 'title', 'content')
上の例では、 ‘url’, ‘title’, ‘content’ フィールドだけが順番にフォームに表示 されます。
Note
この fields
オプションと fieldsets
オプションの中の fields
キーとを混同しないでくださいね。
ModelAdmin.
exclude
¶この属性にフィールドの名前のリストを指定すると、指定したフィールドがフォー ムから除去されます。
例えば、以下のようなモデルがあったとします:
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)
name
と title
フィールドだけを含む Author
モデルのフォームを
表示したければ、 fields
や exclude
を使って、それぞれ以下のように
定義できます:
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title')
class AuthorAdmin(admin.ModelAdmin):
exclude = ('birth_date',)
Author
モデルは 3 つのフィールド name
, title
, birth_date
しか持たないので、上の 2 つの例は全く同じフィールドを含むフォームを生成しま
す。
ModelAdmin.
filter_horizontal
¶ユーザビリティが紙一重の <select multiple>
の代わりに、気の利いた控えめ
な Javascript の「フィルタ」インタフェースを使います。フィルタインタフェー
スを横並びにして表示させたいフィールドのリストを指定してください。フィルタ
インタフェースを縦並びにしたい場合は filter_vertical
を使ってください。
ModelAdmin.
filter_vertical
¶filter_horizontal
とほぼ同じですが、フィルタインタフェースを縦並びで表
示します。
ModelAdmin.
list_display
¶admin の変更リストページに表示するフィールドを制御するには list_display
を使います。
使い方:
list_display = ('first_name', 'last_name')
list_display
を指定しなければ、 admin サイトは各オブジェクトの
__unicode__()
表現を表示するカラムを一つだけ表示します。
list_display
には 4 通りの設定方法があります:
モデルのフィールド名:
class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name')モデルインスタンスを引数にとる呼び出し可能オブジェクト:
def upper_case_name(obj): return "%s %s" % (obj.first_name, obj.last_name).upper() upper_case_name.short_description = 'Name' class PersonAdmin(admin.ModelAdmin): list_display = (upper_case_name,)
ModelAdmin
の属性名を表す文字列。呼び出し可能オブジェクトと同じよ うに動作します:class PersonAdmin(admin.ModelAdmin): list_display = ('upper_case_name',) def upper_case_name(self, obj): return "%s %s" % (obj.first_name, obj.last_name).upper() upper_case_name.short_description = 'Name'モデルの属性名を表す文字列。ただし、
self
はモデルインスタンスを 表します:class Person(models.Model): name = models.CharField(max_length=50) birthday = models.DateField() def decade_born_in(self): return self.birthday.strftime('%Y')[:3] + "0's" decade_born_in.short_description = 'Birth decade' class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'decade_born_in')
list_display
にはいくつか特殊なケースがあります:
フィールドが
ForeignKey
の場合、関連づけられているオブジェクトの__unicode__()
を表示します。
ManyToManyField
フィールドの表示は、テーブルの各行に対して個別に SQL 文を実行することになってしまうのでサポートしていません。どうして も表示させたいなら、カスタムメソッドをモデルに実装して、メソッドの名 前をlist_display
に追加してください (list_display
へのカスタ ムメソッドの追加については、後で詳しく説明しています)。フィールドが
BooleanField
やNullBooleanField
の場合、True
やFalse
の代りに “オン” や “オフ” を示すアイコンを表示 します。モデルや
ModelAdmin
のメソッド、呼び出し可能オブジェクトの名前を 指定した場合、 Django はデフォルトでメソッドの出力を HTML エスケープ します。メソッドの出力をエスケープしたくない場合には、メソッドのallow_tags
属性の値をTrue
にしてください。以下に例を示します:
class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) color_code = models.CharField(max_length=6) def colored_name(self): return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name) colored_name.allow_tags = True class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'colored_name')
True
かFalse
を返すようなモデルのModelAdmin
のメソッド、 呼び出し可能オブジェクトの名前を指定した返す場合、メソッドのboolean
属性をTrue
に設定しておくと、Django は「オン」や「オ フ」のアイコンを表示します。以下に例を示します:
class Person(models.Model): first_name = models.CharField(max_length=50) birthday = models.DateField() def born_in_fifties(self): return self.birthday.strftime('%Y')[:3] == '195' born_in_fifties.boolean = True class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'born_in_fifties')
__str__()
および__unicode__()
メソッドは他のモデルメソッドと 同じようにlist_display
に入れられるので、以下のように書いても全 く問題ありません:list_display = ('__unicode__', 'some_other_field')通常、
list_display
の要素のうち、実際のデータベースのフィールド に対応していないものは、変更リストページで並び順を変えるときのカラム には使えません。 Django はソートをすべてデータベースレベルで行うから です。ただし、
list_display
のいずれかの要素が実際にデータベース上のあ るフィールドを指している場合、admin_order_field
という属性を使っ て、 Django にそのことを教えられます。例を示しましょう:
class Person(models.Model): first_name = models.CharField(max_length=50) color_code = models.CharField(max_length=6) def colored_first_name(self): return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name) colored_first_name.allow_tags = True colored_first_name.admin_order_field = 'first_name' class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'colored_first_name')この例では、 Django は Admin 上で
colored_first_name
を並べ変える 際にfirst_name
フィールドを使います。
ModelAdmin.
list_display_links
¶list_display_links
を設定すると、 list_display
のどのフィールドを
オブジェクトの「変更」ページにリンクするかを制御できます。
デフォルトでは、変更リストページはオブジェクトの変更ページ中の第一カラム、
すなわち list_display
の先頭に指定したフィールドにリンクを張ります。
list_display_links
を使うと、リンク先のカラムを変更できます。
list_display_links
には、フィールド名のリストまたはタプルを
(list_display
と同じ形式で) 指定します。
list_display_links
に指定するフィールド名は、一つでも複数でも構いません。
フィールド名が list_display
に列挙されている限り、 Django はどんなに多
くの (あるいはどんなにわずかな) フィールドがリンクされていても問題にしませ
ん。必要なのは、 list_display_links
を使うには list_display
を定義
しておかねばならない、ということだけです。
以下の例では、 first_name
および last_name
フィールドが変更リス
トページにリンクされます:
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'birthday')
list_display_links = ('first_name', 'last_name')
ModelAdmin.
list_editable
¶Set list_editable
to a list of field names on the model which will allow
editing on the change list page. That is, fields listed in list_editable
will be displayed as form widgets on the change list page, allowing users to
edit and save multiple rows at once.
Note
list_editable
interacts with a couple of other options in particular
ways; you should note the following rules:
- Any field in
list_editable
must also be inlist_display
. You can’t edit a field that’s not displayed!- The same field can’t be listed in both
list_editable
andlist_display_links
– a field can’t be both a form and a link.
You’ll get a validation error if either of these rules are broken.
ModelAdmin.
list_filter
¶admin の変更リストページの右側のサイドバーにあるフィルタを有効にするには、
list_filter
を設定します。この値はフィールド名のリストにします。
各フィールド名は BooleanField
, CharField
, DateField
,
DateTimeField
, IntegerField
, ForeignKey
のいずれかでなければ
なりません。
以下の例は django.contrib.auth.models.User
モデルからとったもので、
list_display
と list_filter
の仕組みを示しています:
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser')
上のコードによって、 admin の変更リストは以下のようになります:
(この例では、後述の search_fields
も定義しています。)
ModelAdmin.
list_per_page
¶admin 変更リストをページ分割 (paginate) で表示するときに、各ページに何個の
アイテムを表示するかを決めます。デフォルト値は 100
です。
list_select_related
を設定すると、 admin の変更リストページに表示するオ
ブジェクトリストを取得する際に select_related()
を使うよう Django に指
示できます。これにより、データベースクエリの発行数を抑えられます。
値は True
または False
にします。デフォルトは False
です。
list_display
のいずれかのフィールドが ForeignKey
の場合、 Django は
この設定に関わらず select_related()
を使います。
select_related()
の詳細は
select_related() のドキュメント を参照してください。
ModelAdmin.
inlines
¶後述の InlineModelAdmin
を参照してください。
ModelAdmin.
ordering
¶ordering
を設定すると、 admin の変更リストにおける整列順を指定できます。
値はタプルからなるリストで、モデルの ordering
パラメタと同じ形式で指定
します。
この値を指定しない場合、 Django はモデルのデフォルトの整列順を使います。
Note
Django はリストやタプルの最初の要素だけを考慮して、後の要素は無視します。
ModelAdmin.
prepopulated_fields
¶フィールドの値を別のフィールドの値からセットさせたい場合は、以下のように、
prepopulated_fields
にフィールド名を対応付けた辞書を設定してください:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
prepopulated_fields
をセットすると、フィールドに小さな JavaScript のア
クションが設定され、引数に指定したフィールドから値を自動的に取り込みます。
prepopulated_fields
は、主に他の複数のフィールドから SlugField
フィー
ルドの値を生成するときに使います。値は、まず各ソースフィールドの値を結合し
て、その結果が有効なスラグになるよう変換 (スペースをダッシュに置換するなど)
して生成します。
DateTimeField
, ForeignKey
および ManyToManyField
は
prepopulated_fields
に指定できません。
ModelAdmin.
radio_fields
¶デフォルトでは、Django の admin は ForeignKey
のフィールドや
choices
の設定されたフィールドに対してセレクタボックス (<select>) イン
タフェースを使います。 radio_fields
にフィールド名を指定しておくと、
Django はセレクタボックスの代りにラジオボタンのインタフェースを使います。
例えば、 group
が Person
モデル上の ForeignKey
フィールド
であれば、以下のように書けます:
class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}
ラジオボタンの並び方を指定するシンボル、 HORIZONTAL
または VERTICAL
は django.contrib.admin
モジュールにあります。
ForeignKey
や choices
パラメタのセットされたフィールド以外に
radio_fields
を使ってはなりません。
ModelAdmin.
raw_id_fields
¶デフォルトでは、Django の admin サイトは ForeignKey
フィールドに対して
セレクタボックス (<select>) インタフェースを使います。しかし、時にはリレー
ション先の全てのオブジェクトの入ったセレクタボックスが生成され、ドロップダ
ウン表示されるのを避けたい場合もあります。
raw_id_fields
には、ウィジェットを Input
に変更したいフィールドのリ
ストを指定します。 ForeignKey
または ManyToManyField
を指定できます:
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ("newspaper",)
ModelAdmin.
save_as
¶save_as
を指定すると、 admin の編集フォームで「別名で保存 (save as)」機
能を使えるようになります。
通常、編集フォームには三つの保存オプション、すなわち「保存 (Save)」、「保存
して編集を続ける (Save and continue editing)」、「保存してもう一つ追加
(Save and add another)」があります。 save_as
を True
にすると「保存
してもう一つ追加」は「別名で保存 (Save as)」に置き換わります。
「別名で保存」は、現在のオブジェクトをそのまま保存するのではなく、(新たな ID を持った) 別のオブジェクトとして保存することです。
デフォルトでは、 save_as
は False
に設定されています。
ModelAdmin.
save_on_top
¶save_on_top
を指定すると、 admin の変更フォームの最上部に保存ボタンを追
加できます。
通常、保存ボタンはフォームの最下部だけに表示されます。 save_on_top
を指
定すると、ボタンは最下部だけでなく最上部にも表示されます。
デフォルトでは、 save_on_top
は False
です。
ModelAdmin.
search_fields
¶search_fields
を指定すると、 admin の変更リストページで検索ボックスを使
えるようになります。この値は、ユーザが検索クエリをテキストボックスに入力し
たときに検索の対象に含めるフィールド名のリストです。
フィールドは CharField
や TextField
のような何らかのテキストフィー
ルドでなければなりません。 DB API の「リレーションを追跡する」表記を使えば、
ForeignKey
を介したフィールドの指定も行えます:
search_fields = ['foreign_key__related_fieldname']
admin の検索ボックスで検索を実行すると、 Django は検索クエリを単語に分解し
て、各単語を含むような全てのオブジェクトを返します。検索は大小文字を区別せ
ず、 search_fields
に指定したフィールドのうち少なくとも一つに単語が入っ
ていればヒットします。例えば、 search_fields
が
['first_name', 'last_name']
に設定されている場合、ユーザが
john lennon
を検索すると、 Django は以下のような WHERE
節を持った
SQL と等価な検索を実行します:
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
より高速な、あるいはより制約の厳しい検索を行うには、フィールド名の前に以下 のような演算子を置きます:
^
フィールドの先頭にマッチします。例えば、 search_fields
を
['^first_name', '^last_name']
にして、ユーザが john lennon
を検
索した場合、Django は以下のような WHERE
節の SQL に等価な検索を実行
します:
WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
このクエリを使うと、データベースはカラムの先頭部分だけをチェックすれば
よく、カラム中のデータ全体を調べなくてもよくなるため、通常の
'%john%'
クエリよりも効率的に検索を実行できます。加えて、カラムにイ
ンデクスが設定されていれば、データベースによっては LIKE
クエリであっ
てもインデクスを使ったクエリを実行できるという利点があります。
=
大小文字を区別しない厳密一致です。例えば、 search_fields
を
['=first_name', '=last_name']
にして、ユーザが john lennon
を検
索した場合、 Django は以下のような WHERE
節の SQL に等価な検索を実行
します:
WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
クエリ入力はスペース区切りなので、この例に従うと、 first_name
が
'john winston'
である (スペースを含む) ようなレコードは検索でき
ないので注意してください。
@
ModelAdmin.
formfield_overrides
¶This provides a quick-and-dirty way to override some of the
Field
options for use in the admin.
formfield_overrides
is a dictionary mapping a field class to a dict of
arguments to pass to the field at construction time.
Since that’s a bit abstract, let’s look at a concrete example. The most common
use of formfield_overrides
is to add a custom widget for a certain type of
field. So, imagine we’ve written a RichTextEditorWidget
that we’d like to
use for large text fields instead of the default <textarea>
. Here’s how we’d
do that:
from django.db import models
from django.contrib import admin
# Import our custom widget and our model from where they're defined
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': RichTextEditorWidget},
}
Note that the key in the dictionary is the actual field class, not a string.
The value is another dictionary; these arguments will be passed to
__init__()
. See フォーム API for details.
Warning
If you want to use a custom widget with a relation field (i.e.
ForeignKey
or
ManyToManyField
), make sure you haven’t included
that field’s name in raw_id_fields
or radio_fields
.
formfield_overrides
won’t let you change the widget on relation fields
that have raw_id_fields
or radio_fields
set. That’s because
raw_id_fields
and radio_fields
imply custom widgets of their own.
ModelAdmin.
actions
¶A list of actions to make available on the change list page. See Admin actions for details.
ModelAdmin.
actions_on_top
¶ModelAdmin.
actions_on_bottom
¶Controls where on the page the actions bar appears. By default, the admin
changelist displays actions at the top of the page (actions_on_top = True;
actions_on_bottom = False
).
ModelAdmin.
change_list_template
¶Path to a custom template that will be used by the model objects “change list” view. Templates can override or extend base admin templates as described in Overriding Admin Templates.
If you don’t specify this attribute, a default template shipped with Django that provides the standard appearance is used.
ModelAdmin.
change_form_template
¶Path to a custom template that will be used by both the model object creation and change views. Templates can override or extend base admin templates as described in Overriding Admin Templates.
If you don’t specify this attribute, a default template shipped with Django that provides the standard appearance is used.
ModelAdmin.
object_history_template
¶Path to a custom template that will be used by the model object change history display view. Templates can override or extend base admin templates as described in Overriding Admin Templates.
If you don’t specify this attribute, a default template shipped with Django that provides the standard appearance is used.
ModelAdmin.
delete_confirmation_template
¶Path to a custom template that will be used by the view responsible of showing the confirmation page when the user decides to delete one or more model objects. Templates can override or extend base admin templates as described in Overriding Admin Templates.
If you don’t specify this attribute, a default template shipped with Django that provides the standard appearance is used.
ModelAdmin
のメソッド¶ModelAdmin.
save_model
(self, request, obj, form, change)¶save_model
メソッドは HttpRequest
, モデルインスタンス、
ModelForm
インスタンス、オブジェクトの追加か変更かを表すブール値 (変更
の場合には True
) を引数にとります。このメソッドを使えば、オブジェクトの
保存前 (pre-save) および保存後 (post-save) 処理を実行できます。
保存前に request.user
をオブジェクトに保存するには、以下のようにします:
class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.save()
ModelAdmin.
save_formset
(self, request, form, formset, change)¶save_formset
メソッドは HttpRequest
, モデルインスタンス、親クラスの
ModelForm
インスタンス、オブジェクトの追加か変更かを表すブール値 (変更
の場合には True
) を引数にとります。
フォームセットの各モデルインスタンスの保存前に request.user
をオブジェ
クトに保存するには、以下のようにします:
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
ModelAdmin.
get_urls
(self)¶The get_urls
method on a ModelAdmin
returns the URLs to be used for
that ModelAdmin in the same way as a URLconf. Therefore you can extend them as
documented in URL ディスパッチャ:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = patterns('',
(r'^my_view/$', self.my_view)
)
return my_urls + urls
Note
Notice that the custom patterns are included before the regular admin URLs: the admin URL patterns are very permissive and will match nearly anything, so you’ll usually want to prepend your custom URLs to the built-in ones.
However, the self.my_view
function registered above suffers from two
problems:
- It will not perform and permission checks, so it will be accessible to the general public.
- It will not provide any header details to prevent caching. This means if the page retrieves data from the database, and caching middleware is active, the page could show outdated information.
Since this is usually not what you want, Django provides a convenience wrapper
to check permissions and mark the view as non-cacheable. This wrapper is
AdminSite.admin_view()
(i.e. self.admin_site.admin_view
inside a
ModelAdmin
instance); use it like so:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = patterns('',
(r'^my_view/$', self.admin_site.admin_view(self.my_view))
)
return my_urls + urls
Notice the wrapped view in the fifth line above:
(r'^my_view/$', self.admin_site.admin_view(self.my_view))
This wrapping will protect self.my_view
from unauthorized access and will
apply the django.views.decorators.cache.never_cache
decorator to make sure
it is not cached if the cache middleware is active.
If the page is cacheable, but you still want the permission check to be performed,
you can pass a cacheable=True
argument to AdminSite.admin_view()
:
(r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
ModelAdmin.
formfield_for_foreignkey
(self, db_field, request, **kwargs)¶The formfield_for_foreignkey
method on a ModelAdmin
allows you to
override the default formfield for a foreign key field. For example, to
return a subset of objects for this foreign key field based on the user:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return db_field.formfield(**kwargs)
return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
This uses the HttpRequest
instance to filter the Car
foreign key field
to only the cars owned by the User
instance.
ModelAdmin.
add_view
(self, request, form_url='', extra_context=None)¶Django view for the model instance addition page. See note below.
ModelAdmin.
change_view
(self, request, object_id, extra_context=None)¶Django view for the model instance edition page. See note below.
ModelAdmin.
changelist_view
(self, request, extra_context=None)¶Django view for the model instances change list/actions page. See note below.
ModelAdmin.
delete_view
(self, request, object_id, extra_context=None)¶Django view for the model instance(s) deletion confirmation page. See note below.
ModelAdmin.
history_view
(self, request, object_id, extra_context=None)¶Django view for the page that shows the modification history for a given model instance.
Unlike the hook-type ModelAdmin
methods detailed in the previous section,
these five methods are in reality designed to be invoked as Django views from
the admin application URL dispatching handler to render the pages that deal
with model instances CRUD operations. As a result, completely overriding these
methods will significantly change the behavior of the admin application.
One comon reason for overriding these methods is to augment the context data that is provided to the template that renders the view. In the following example, the change view is overridden so that the rendered template is provided some extra mapping data that would not otherwise be available:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
def change_view(self, request, object_id, extra_context=None):
my_context = {
'osm_data': self.get_osm_info(),
}
return super(MyModelAdmin, self).change_view(request, object_id,
extra_context=my_context)
ModelAdmin
のメディア定義¶たまに、 CSS や JavaScript を追加・変更ビューに追加したい場合があります。
ModelAdmin
に内部クラス Media
を定義すれば、これを実現できます:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
これらのメディア名のパスには MEDIA_URL
の内容が前置されます。また、
forms の通常のメディア定義 と同じ規則が当てはま
ります。
admin にカスタムのバリデーションを追加するのはとても簡単です。 admin インタ
フェースは django.forms
を再利用しているので、 ModelAdmin
クラス
を使えばフォームを指定できます:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm
は、 import できる場所ならどこにでも置けます。フォー
ムの中で、任意のフィールドにカスタムのバリデーションコードを追加できます:
class MyArticleAdminForm(forms.ModelForm):
class Meta:
model = Article
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
このとき、 ModelForm
を使うことが重要です。他のクラスではうまくいきませ
ん。詳しくは forms ドキュメント内の
カスタムのバリデーション を参照してください。
モデルフォームのバリデーションに関する注意
にも、さらに詳しい情報があります。
InlineModelAdmin
オブジェクト¶admin インタフェースには、他のモデルクラスのインスタンスを同じページで編集 する機能があります。この機能をインライン編集と呼びます。例えば以下のような 二つのモデルがあったとします:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
ある著者 (Author) オブジェクトのページで、著者の書いた本 (Book) オブジェク
トの情報を編集したいなら、 ModelAdmin.inlines
属性に
InlineModelAdmin
を指定します:
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
Django は、 InlineModelAdmin
のサブクラスとして、以下の二つを提供してい
ます:
* ``TabularInline``
* ``StackedInline``
これら二つの違いは、単にレンダリングに使われるテンプレートに過ぎません。
InlineModelAdmin
のオプション¶InlineModelAdmin
クラスは ModelAdmin
のサブクラスなので、以下に挙げ
る独自の機能の他に、 ModelAdmin
の機能を全て継承しています:
model
¶インライン編集する対象のモデルです。必須の引数です。
fk_name
¶モデルの外部キーの名前です。たいていの場合、外部キーは自動的に決定できます
が、親モデルに対して外部キーを複数張っているようなモデルの場合は、
fk_name
を明示的に決める必要があります。
formset
¶デフォルト値は BaseInlineFormset
です。独自のフォームセットを指定すれば、
色々とカスタマイズできます。インラインオブジェクトのフォームは
モデルフォームセット で生成されています。
form
¶form
の値は ModelAdmin
から継承されます。この値は、インラインオブジェ
クトのフォームセットを生成するときに fomrset_factory
に渡されます。
extra
¶フォームセットが、初期のフォームに加えて表示する追加のフォーム数を制御しま す。詳しくは formsets のドキュメント を参照 してください。
max_num
¶インラインで表示するフォームの最大個数を制御します。この値は直接オブジェク トの数には関係しませんが、あまり小さな値が設定されていると、影響することも あります。詳しくは 編集可能なオブジェクトの数を制限する を参照してください。
raw_id_fields
¶デフォルトの設定では、 Django の admin は ForeignKey
の選択に選択ボック
スインタフェース (<select>) を使います。しかし、リレーション先の全てのイン
スタンスをドロップダウンに表示するときのオーバヘッドを防ぎたいときがありま
す。
raw_id_fields
には、モデルの ForeignKey
や ManyToManyField
をリ
ストで指定します。 raw_id_fields
に指定したフィールドは、 Input
ウィ
ジェットを使います:
class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ("pages",)
template
¶インラインオブジェクトをレンダリングするときに使われるテンプレートです。
verbose_name
¶モデルの内部クラス Meta
の verbose_name
の設定をオーバライドします。
verbose_name_plural
¶モデルの内部クラス Meta
の verbose_name_plural
の設定をオーバライド
します。
一つのモデルに対して、複数の外部キーが張られている場合があります。以下のよ うなモデルを例に考えてみましょう:
class Friendship(models.Model):
to_person = models.ForeignKey(Person, related_name="friends")
from_person = models.ForeignKey(Person, related_name="from_friends")
Person
の admin サイトで、インラインの追加・編集ページを表示したくても、
どの外部キーを辿らせるかは自動で決められません。従って、明示的に決めてやる
必要があります:
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
デフォルトの設定では、 admin で多対多のリレーションを表す場合、
ManyToManyField
を定義しているモデルの中でインライン表示されるウィジェッ
トを使います。しかし、 ManyToManyField
の through
引数に中間モデル
を指定した場合、 admin は ManyToManyField
のウィジェットを表示しません。
これは、中間モデルの各インスタンスを表示するのに一つのウィジェットでは足り
ないためと、複数ウィジェットを表示するために必要なレイアウトが中間モデルに
よって変わってしまうためです。
しかし、それでもインラインで編集を行いたい場合があります。好運なことに、イ ンライン admin モデル (inline admin model) を使えば簡単に実現できます。 例として、以下のようなモデルを考えましょう:
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
中間モデルを admin で表示するには、まず Membership
モデルに対するインラ
インクラスを作成します:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
上の簡単な例では、 InlineModelAdmin
のデフォルトの設定を使って
Membership
モデルのインライン admin を定義しています。ただし、追加用の
フォームの数を 1 つに制限しています。他にも、 InlineModelAdmin
クラスの
オプションを使えば、色々な設定をカスタマイズできます。
次に、 Person
や Group
モデルの ModelAdmin
クラスを定義します:
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
最後に、 Person
と Group
を admin サイトに登録します:
admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)
これで、 admin サイトの Person
と Group
の両方で、
Membership
オブジェクトをインライン編集できます。
一般化リレーションオブジェクトもインラインで扱えます。以下のようなモデルが 定義されていたとしましょう:
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Product
の追加/変更ビューで Image
インスタンスを編集したり追加した
りしたいなら、 django.contrib.contenttypes.generic
の
GenericInlineModelAdmin
を使います。 admin.py
で、以下のように設定
してください:
from django.contrib import admin
from django.contrib.contenttypes import generic
from myproject.myapp.models import Image, Product
class ImageInline(generic.GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
django.contrib.contenttypes.generic
は GenericTabularInline
と
GenericStackedInline
を提供していて、その動作は通常のインライン編集と
同じです。詳しくは contenttypes のドキュメント を参照してください。
admin モジュールが admin サイトの様々なページを生成するときに使うテンプレー トは、その大半を比較的簡単にオーバライドできます。オーバライドは、特定のア プリケーションやモデルだけのためにもオーバライドできます。
admin テンプレートファイルは contrib/admin/templates/admin
ディレクトリ
に入っています。
テンプレートをオーバライドするには、まずプロジェクトの templates
ディレ
クトリ内に admin
ディレクトリを作成します。プロジェクトのテンプレートディ
レクトリとは、 TEMPLATE_DIRS
の中に設定されているディレクトリのいずれか
です。
次に、 admin
ディレクトリ内に、アプリケーションの名前から取った名前のディ
レクトリを作成します。アプリケーションのサブディレクトリの中に、さらにモデ
ルからとった名前のサブディレクトリを作成します。このとき、 admin アプリケー
ションはモデル名を小文字に変換した名前でディレクトリを探すことに注意しましょ
う。ですから、大小文字を区別するファイルシステム上にアプリケーションを配置
しているのなら、ディレクトリ名が全て小文字で構成されているか確認してくださ
い。
特定のアプリケーション向けに admin テンプレートをオーバライドしたければ、テ
ンプレートを django/contrib/admin/templates/admin
からアプリケーション
名のディレクトリ下にコピーして編集してください。
例えば、 my_app
の全てのモデルの変更リストにツールメニューを追加したい
なら、 contrib/admin/templates/admin/change_list.html
をプロジェクトの
templates/admin/my_app/
ディレクトリにコピーして必要な変更を施します。
Page
という名前のモデルの変更リストだけにツールメニューを追加したいなら、
ファイルを templates/admin/my_app/page
ディレクトリにコピーします。
admin テンプレートはモジュラー構造で設計されているので、必ずしもいつもテン プレート全体を置き換える必要はありませんし、そうしないよう勧めます。基本的 には、変更の必要のあるセクションだけをオーバライドするのがよいでしょう。
上に挙げた例の続きとして説明しましょう。 Page
モデルの History
ツー
ルの隣に新しくリンクを追加したいとします。 change_from.html
を眺めたあ
と、オーバライドする必要があるのは object-tools
ブロックだけだと分かっ
たとしましょう。その場合、新たな change_form.html
は以下のように書けま
す:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
<li><a href="history/" class="historylink">{% trans "History" %}</a></li>
<li><a href="mylink/" class="historylink">My Link</a></li>
{% if has_absolute_url %}
<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
{% trans "View on site" %}</a>
</li>
{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
これだけです!このファイルを templates/admin/my_app
ディレクトリに置け
ば、全てのモデル変更フォームでリンクが表示されるでしょう。
contrib/admin/templates/admin
のテンプレートの全てが、アプリケーション
やモデル単位でオーバライドできるわけではありません。以下のテンプレートはオー
バライドできます:
app_index.html
change_form.html
change_list.html
delete_confirmation.html
object_history.html
この節で述べた方法でテンプレートをオーバライドできなくても、オーバライドし
たい内容を templates/admin
ディレクトリに配置することで、プロジェクト全
体の設定としてオーバライドできます。この方法は、カスタムの 404 ページや 500
ページをオーバライドするときに特に便利です。
Note
change_list_request.html
のようなテンプレートは、カスタムの
inclusion タグをレンダするために使われています。このテンプレートはオー
バライドできますが、テンプレートを変更するときには、独自の inclusion タ
グを作成しておいて、別の名前を付けておき、テンプレートで呼び出す方が
よいでしょう。そうすれば、テンプレートを選択して使えるからです。
インデクスページやログインページのテンプレートを変更したければ、
AdminSite
インスタンスを自作して、
AdminSite.index_template
や AdminSite.login_template
プロパ
ティの値を変更してください。
AdminSite
オブジェクト¶AdminSite
(name=None)¶Django の管理サイトは django.contrib.admin.sites.AdminSite
のインスタン
スを使って表現しています。デフォルトでは、このクラスのインスタンスは
django.contrib.admin.site
としてすでに作成されていて、モデルや
ModelAdmin
インスタンスを登録できます。
独自のふるまいを実現する管理サイトを作りたければ、 AdminSite
のサブクラ
スを作成して、必要に応じてオーバライドや機能追加を行ってください。その後で、
作成したサブクラスを (他の Python クラスと同様に) 素直にインスタンス化して、
デフォルトの AdminSite
インスタンスにモデルや ModelAdmin
サブクラス
を登録する代りに、作成したインスタンスに登録してください。
When constructing an instance of an AdminSite
, you are able to provide
a unique instance name using the name
argument to the constructor. This
instance name is used to identify the instance, especially when
reversing admin URLs. If no instance name is
provided, a default instance name of admin
will be used.
AdminSite
attributes¶AdminSite.
index_template
¶Path to a custom template that will be used by the admin site main index view. Templates can override or extend base admin templates as described in Overriding Admin Templates.
AdminSite.
login_template
¶Path to a custom template that will be used by the admin site login view. Templates can override or extend base admin templates as described in Overriding Admin Templates.
AdminSite
インスタンスをフックする¶Django admin サイト構築の最後のステップは、 AdminSite
インスタンスの
URLconf への設置です。設置を行うには、 URL を AdminSite.urls
メソッドに
振り向けます。
以下の例では、デフォルトの AdminSite
インスタンスである
django.contrib.admin.site
を、 /admin/
という URL にマップしていま
す:
# urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
('^admin/', include(admin.site.urls)),
上の例では、 admin.autodiscover()
を使って、 INSTALLED_APPS
の
admin.py
モジュールを自動的にロードしています。
次の例では、 AdminSite
インスタンス myproject.admin.admin_site
を /myadmin/
という URL にマップしています:
# urls.py
from django.conf.urls.defaults import *
from myproject.admin import admin_site
urlpatterns = patterns('',
('^myadmin/', include(admin_site.urls)),
)
自作した AdminSite
を使っているのなら、 myproject.admin
モジュール
の中で各アプリケーションの admin.py モジュールを import しているはずなので、
autodiscover
を呼ぶ必要はありません。
Django で作られた一つの Web サイト上で、複数の admin サイトインスタンスを簡
単に運営できます。方法は、単に AdminSite
インスタンスを複数にして別々の
URL で設置するだけです。
AdminSite
instances into urls has changed in
Django 1.1.下の例では、 /basic-admin/
と /advanced-admin/
という二つの URL で、
myproject.admin.basic_site
と myproject.admin.advanced_site
という
AdminSite
インスタンスを使って、別々のバージョンの admin サイトを運営し
ています:
# urls.py
from django.conf.urls.defaults import *
from myproject.admin import basic_site, advanced_site
urlpatterns = patterns('',
('^basic-admin/', include(basic_site.urls)),
('^advanced-admin/', include(advanced_site.urls)),
)
AdminSite
instances take a single argument to their constructor, their
name, which can be anything you like. This argument becomes the prefix to the
URL names for the purposes of reversing them. This
is only necessary if you are using more than one AdminSite
.
Just like ModelAdmin
, AdminSite
provides a
get_urls()
method
that can be overridden to define additional views for the site. To add
a new view to your admin site, extend the base
get_urls()
method to include
a pattern for your new view.
Note
Any view you render that uses the admin templates, or extends the base
admin template, should provide the current_app
argument to
RequestContext
or Context
when rendering the template. It should
be set to either self.name
if your view is on an AdminSite
or
self.admin_site.name
if your view is on a ModelAdmin
.
When an AdminSite
is deployed, the views provided by that site are
accessible using Django’s URL reversing system.
The AdminSite
provides the following named URL patterns:
Page URL name Parameters Index index
Logout logout
Password change password_change
Password change done password_change_done
i18n javascript jsi18n
Application index page app_list
app_label
Each ModelAdmin
instance provides an additional set of named URLs:
Page URL name Parameters Changelist {{ app_label }}_{{ model_name }}_changelist
Add {{ app_label }}_{{ model_name }}_add
History {{ app_label }}_{{ model_name }}_history
object_id
Delete {{ app_label }}_{{ model_name }}_delete
object_id
Change {{ app_label }}_{{ model_name }}_change
object_id
These named URLs are registered with the application namespace admin
, and
with an instance namespace corresponding to the name of the Site instance.
So - if you wanted to get a reference to the Change view for a particular
Choice
object (from the polls application) in the default admin, you would
call:
>>> from django.core import urlresolvers
>>> c = Choice.objects.get(...)
>>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,))
This will find the first registered instance of the admin application (whatever the instance
name), and resolve to the view for changing poll.Choice
instances in that instance.
If you want to find a URL in a specific admin instance, provide the name of that instance
as a current_app
hint to the reverse call. For example, if you specifically wanted
the admin view from the admin instance named custom
, you would need to call:
>>> change_url = urlresolvers.reverse('custom:polls_choice_change', args=(c.id,))
For more details, see the documentation on reversing namespaced URLs.
Oct 26, 2017