Django の admin サイト¶
Django のパワフルな特徴の1つは、自動的に生成される admin インタフェースです。あなたのモデルクラスからメタデータを読み取り、モデル中心のインタフェースを提供します。このインタフェースのおかげで、ユーザはあなたのサイトのコンテンツを操作できます。admin サイトのオススメの使い方は、組織内で利用する管理ツールに利用を制限することです。admin サイトは、あなたのサイトのフロントエンドやその周辺を含んだ全体を作成することを意図していません。
admin サイトは、カスタマイゼーションのためのたくさんのフックを持っています。しかしそれらのフックを使う際には気をつけてください。もしあなたが、データベースのテーブルとフィールドを使用しないような、よりプロセス中心のインタフェースを提供する必要があるなら、おそらく自分でビューを書いたほうが良いでしょう。
このドキュメントでは、Django の admin インタフェースを有効にして使用したりカスタマイズする方法について説明します。
概要¶
admin サイトは startproject で使用されるデフォルトのプロジェクトテンプレートで有効になります。
デフォルトのプロジェクトテンプレートを使用していない場合、要件は以下の通りです:
'django.contrib.admin'とその依存関係であるdjango.contrib.auth,django.contrib.contenttypes,django.contrib.messages, およびdjango.contrib.sessionsを、INSTALLED_APPS設定に追加してください。DjangoTemplatesバックエンドを、TEMPLATES設定で構成し、django.template.context_processors.request,django.contrib.auth.context_processors.auth, およびdjango.contrib.messages.context_processors.messagesをOPTIONSの'context_processors'オプションに含めてください。MIDDLEWARE設定をカスタマイズしている場合、django.contrib.sessions.middleware.SessionMiddleware、django.contrib.auth.middleware.AuthenticationMiddleware、およびdjango.contrib.messages.middleware.MessageMiddlewareを含める必要があります。
これらのステップを踏んだ後、フックしたURL (デフォルトでは /admin/) を訪れることで、管理サイトを使用できるようになります。
ログイン用のユーザーを作成する必要がある場合は、createsuperuser コマンドを使用してください。デフォルトでは、管理サイトにログインするにはユーザーの is_staff 属性が True に設定されている必要があります。
最後に、アプリケーションのモデルのうちどれが管理インターフェースで編集可能であるべきかを決定します。それらのモデルごとに、ModelAdmin に記述されているように、管理サイトに登録します。
他のトピック¶
参考
本番環境での admin と関連する静的ファイル (画像、JavaScript、CSS) の配信について知りたい場合は、ファイルを配信する を参照してください。
問題が解決しない場合は、FAQ: 管理インタフェース を参照してみてください。
ModelAdmin のオブジェクト¶
- class ModelAdmin[ソース]¶
ModelAdminクラスは、admin インターフェース内でモデルを表現する方法です。通常、アプリケーション内のadmin.pyに記述されます。ModelAdminの例を見てみましょう:from django.contrib import admin from myapp.models import Author class AuthorAdmin(admin.ModelAdmin): pass admin.site.register(Author, AuthorAdmin)
いつでも
ModelAdminオブジェクトが必要なのか?上記の例では、ModelAdminクラスはカスタム値を(まだ)定義していません。その結果、デフォルトの管理インターフェースが提供されます。デフォルトのadminインターフェースに満足している場合は、ModelAdminオブジェクトを定義する必要はまったくありません。ModelAdminの記述をせずにモデルクラスを登録できます。上記の例は、次のように簡略化できます。
from django.contrib import admin from myapp.models import Author admin.site.register(Author)
register デコレータ¶
- register(*models, site=django.contrib.admin.sites.site)[ソース]¶
ModelAdminを登録するために、デレコータも用意されています:from django.contrib import admin from .models import Author @admin.register(Author) class AuthorAdmin(admin.ModelAdmin): pass
1 つ以上のモデルが与えられ、
ModelAdminに登録されます。カスタムのAdminSiteを使用している場合、siteキーワード引数を使って渡してください:from django.contrib import admin from .models import Author, Editor, Reader from myproject.admin_site import custom_admin_site @admin.register(Author, Reader, Editor, site=custom_admin_site) class PersonAdmin(admin.ModelAdmin): pass
このデコレータは、model admin クラスをその
__init__()メソッド内で参照する必要がある場合(例:super(PersonAdmin, self).__init__(*args, **kwargs))には使用できません。代わりにsuper().__init__(*args, **kwargs)のようにします。
admin ファイルを見つける¶
INSTALLED_APPS 設定内に 'django.contrib.admin' を記述すると、Django は自動的に各アプリケーション内で admin モジュールを探してインポートします。
- class apps.AdminConfig¶
これは、admin に対するデフォルトの
AppConfigクラスです。Django が開始するとautodiscover()を呼び出します。
- class apps.SimpleAdminConfig¶
このクラスは
AdminConfigと同じように動作しますが、autodiscover()を呼び出しません。- default_site¶
これはデフォルトの admin サイトのクラスやサイトインスタンスを返す呼び出し可能オブジェクトへのドット区切りのインポートパスです。デフォルトは
'django.contrib.admin.sites.AdminSite'です。使い方は デフォルトの admin サイトをオーバーライドする を参照してください。
- autodiscover()[ソース]¶
この関数は、インストールされた各アプリケーション内で
adminモジュールをインポートするよう試みます。これらのモジュールは admin にモデルが登録されているものと想定されます。通常、この機能を手動で呼び出す必要はありません。Django が開始するとき
AdminConfigが呼び出してくれます。
カスタム AdminSite を使用している場合、通常はすべての ModelAdmin サブクラスをコードにインポートし、それらをカスタム AdminSite に登録します。その場合、自動検出を無効にするには、INSTALLED_APPS 設定で 'django.contrib.admin' の代わりに 'django.contrib.admin.apps.SimpleAdminConfig' を指定する必要があります。
ModelAdmin のオプション¶
ModelAdmin は非常に柔軟にできています。インターフェイスをカスタマイズするために、様々なオプションが用意されています。すべてのプションは ModelAdmin サブクラスで定義します:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = "pub_date"
- ModelAdmin.actions_on_top¶
- ModelAdmin.actions_on_bottom¶
ページ上のどこにアクションバーが表示されかをコントロールします。デフォルトでは、admin チェンジリストはページのトップにアクションを表示します (
actions_on_top = True; actions_on_bottom = False)。
- ModelAdmin.actions_selection_counter¶
アクションのドロップダウンの隣に選択用カウンターを表示するかどうかをコントロールします。デフォルトでは、admin チェンジリストは表示するようになっています (
actions_selection_counter = True)。
- ModelAdmin.date_hierarchy¶
date_hierarchyをモデル内のDateFieldかDateTimeFieldの名前にセットすると、チェンジリストのページがそのフィールドによる日付ベースのドリルダウンナビゲーションを含むようになります。実装例:
date_hierarchy = "pub_date"
__ルックアップを使用して、関連するモデルのフィールドを指定することもできます。たとえば:date_hierarchy = "author__pub_date"
この機能は、有効なデータに基づいて、適切に変化させます。たとえば、すべての日付が 1 月に収まっている場合、日のドリルダウンのみを表示します。
注釈
date_hierarchyは内部的にQuerySet.datetimes()を使用します。タイムゾーンサポートが有効 (USE_TZ = True) な際に注意すべき点について、ドキュメントを参照してください。
- ModelAdmin.empty_value_display¶
この属性は、空(
None、空の文字列、等)のレコードのフィールドに対するデフォルトの表示値をオーバーライドします。デフォルト値は-(ダッシュ)です。たとえば:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): empty_value_display = "-empty-"
AdminSite.empty_value_displayですべての admin ページもしくは特定のフィールドに対してempty_value_displayをオーバーライドすることもできます:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): list_display = ["name", "title", "view_birth_date"] @admin.display(empty_value="???") def view_birth_date(self, obj): return obj.birth_date
- ModelAdmin.exclude¶
この属性を使用する場合、フォームから除外するフィールドの名称をリストで指定します。
たとえば、以下のモデルを考えてみましょう:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) title = models.CharField(max_length=3) birth_date = models.DateField(blank=True, null=True)
Authorモデルに対するフォームがnameとtitleの 2 つのフィールドのみを含むようにしたい場合、以下のようにfieldsかexcludeを指定することになります:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): fields = ["name", "title"] class AuthorAdmin(admin.ModelAdmin): exclude = ["birth_date"]
Author モデルが 3 つのフィールド (
name、title、birth_date) しか持っていないので、上記の宣言によって生成されるフォームはまったく同じフィールドを持つことになります。
- ModelAdmin.fields¶
"add" と "change" 上のフォームでシンプルなレイアウト変更 (有効なフィールドのみ表示、順序の変更、行のグルーピングなど) を行うには、
fieldsオプションを使用してください。たとえば、以下のように、django.contrib.flatpages.models.FlatPageモデルに対して admin フォームのよりシンプルなバージョンを定義できます。class FlatPageAdmin(admin.ModelAdmin): fields = ["url", "title", "content"]
上記の例では、指定したフィールド (
url、title、content) だけが (結果として) フォーム上で表示されます。fieldsはModelAdmin.readonly_fieldsで定義される値を持つことができ、読み取り専用で表示されます。より複雑なレイアウトを作るには、
fieldsetsオプションを参照してください。fieldsオプションは、list_displayと同じタイプの値を受け付けますが、呼び出し可能オブジェクトや関連フィールドの__ルックアップは受け付けません。モデルおよびモデル管理クラスのメソッド名は、readonly_fieldsにリストされている場合にのみ使用されます。1 つの行に複数のフィールドを表示するには、タプルで囲んでください。この例では、
urlとtitleフィールドが同じ行に表示され、contentフィールドは次の行に表示されます:class FlatPageAdmin(admin.ModelAdmin): fields = [("url", "title"), "content"]
ModelAdmin.fieldsetsオプションとの混同の可能性この
fieldsオプションと、次のセクションで説明するfieldsetsにおけるfieldsディクショナリキーは別物です。fieldsオプションもfieldsetsオプションも指定されない場合、 Django はデフォルトで次のように表示します。AutoFieldではなく、かつeditable=Trueが設定されている各フィールドを、モデル内で定義された順序で単一のフィールドセットに表示します。その後にreadonly_fieldsで定義されたフィールドを表示します。
- ModelAdmin.fieldsets¶
admin の "add" と "change" ページのレイアウトをコントロールするには、
fieldsetsをセットしてください。fieldsetsは、2 値タプルのリストで、各 2 値タプルは admin フォームページの<fieldset>を表します。 (<fieldset>はフォームの "section" です。)2 値タプルのフォーマットは
(name, field_options)で、nameはフィールドセットのタイトル文字列を表し、field_optionsフィールドセットに関する情報のディクショナリで、表示するフィールドのリストを含みます。django.contrib.flatpages.models.FlatPageモデルを用いた例は以下のようになります。from django.contrib import admin class FlatPageAdmin(admin.ModelAdmin): fieldsets = [ ( None, { "fields": ["url", "title", "content", "sites"], }, ), ( "Advanced options", { "classes": ["collapse"], "fields": ["registration_required", "template_name"], }, ), ]
これにより、admin ページは以下のような見た目となります:
fieldsetsとfieldsオプションのどちらも存在しない場合、Django はデフォルトでAutoFieldとeditable=True以外の各フィールドを、単一のフィールドセットで、モデル内でフィールドが定義されたとおりの順番で表示します。field_optionsディクショナリは以下のキーを持つことができます:fieldsフィールドセット内に表示するフィールド名のリストまたはタプルです。このキーは必須です。
実装例:
{ "fields": ["first_name", "last_name", "address", "city", "state"], }
fieldsオプションと同様に、複数のフィールドを 1 行に表示するにはタプルでこれらのフィールドを囲んでください。この例では、first_nameとlast_nameフィールドが 1 つの行に表示されます。{ "fields": [("first_name", "last_name"), "address", "city", "state"], }
fieldsはModelAdmin.readonly_fieldsで定義される値を持つことができ、読み取り専用で表示されます。fieldsに呼び出し可能オブジェクトの名前を追加した場合、fieldsオプションと同じルールが適用されます: 呼び出し可能オブジェクトはreadonly_fields内でリスト化される必要があります。
classesフィールドセットに適用する追加のCSSクラスを含むリストまたはタプルです。これには、プロジェクト内で定義されたカスタムCSSクラスや、Djangoが提供するCSSクラスを含めることができます。デフォルトの管理サイトのCSSスタイルシート内では、特に役立つ2つのクラス、
collapseとwideが定義されています。実装例:
{ "classes": ["wide", "collapse"], }
wideスタイルが適用されたフィールドセットは、管理インターフェースで追加の横幅が与えられます。collapseスタイルが適用された名前付きフィールドセットは、初期状態で折りたたまれ、表示/非表示を切り替えるための展開可能なウィジェットが使用されます。Changed in Django 5.1:collapseクラスを使用するfieldsetsは、nameが定義されている場合、<details>および<summary>要素を使用するようになりました。
description各フィールドセットの見出しの下に表示されるオプションの追加テキストの文字列です。
この値は、管理インターフェイスに表示されるときにはHTMLエスケープされないことに注意してください。これにより、HTML を含めることができます。あるいは、プレーンテキストと
django.utils.html.escape()を使って HTML の特殊文字をエスケープすることもできます。
TabularInlineはfieldsetsの機能の一部しか利用できませんTabularInlineでfieldsetsを使用する際は、機能が制限されています。TabularInlineレイアウト内で表示するフィールドとその順序を指定するには、field_options辞書内でfieldsを定義する必要があります。その他のすべての機能はサポートされていません。これには、フィールドのグループにタイトルを定義するための
nameの使用が含まれます。
- ModelAdmin.filter_horizontal¶
デフォルトでは、
ManyToManyFieldは<select multiple>で admin サイトで表示されます。複数選択のボックスは、たくさんのアイテムを選択するには不向きです。ManyToManyFieldをこのリストに加えると、代わりにかっこよくて控えめな JavaScript の "filter" インターフェースを使用します。非選択および選択済みのオプションは 2 つのボックスに並べて表示されます。垂直方向のインターフェースを使用するにはfilter_verticalを参照してください。
- ModelAdmin.filter_vertical¶
filter_horizontalと同じですが、フィルタインターフェイスを垂直方向に表示し、非選択のオプションは選択済みのオプションの上部に表示されます。
- ModelAdmin.form¶
デフォルトではモデルに対して
ModelFormが動的に生成されます。追加と変更の両方のページで使用されるフォームです。独自のModelFormを定義すれば、追加と変更のページでフォームの挙動を簡単にオーバーライドできます。あるいは、まったく新しいモデルフォームを作る代わりに、ModelAdmin.get_form()メソッドを使ってデフォルトのフォームをカスタムすることもできます。例については カスタムのバリデーションを admin に追加する を参照してください。
ModelAdmin.excludeが優先されますModelFormとModelAdminの両方でexcludeオプションが定義されている場合、ModelAdminは優先順位に従います。from django import forms from django.contrib import admin from myapp.models import Person class PersonForm(forms.ModelForm): class Meta: model = Person exclude = ["name"] class PersonAdmin(admin.ModelAdmin): exclude = ["age"] form = PersonForm
この例では、生成されるフォームで "age" フィールドは除外されますが "name" フィールドは含まれます。
- ModelAdmin.formfield_overrides¶
admin 内で使用するための
Fieldのうちある程度の部分をオーバーライドする簡単 (だけど汚い) 方法を提供します。formfield_overridesはディクショナリで、フィールドクラスの構成時にフィールドに渡す引数のディクショナリをマッピングします。これでは抽象的すぎるので、具体的な例を見てみましょう。
formfield_overridesのもっとも一般的な使い道は、特定のタイプのフィールドに対してカスタムしたウィジェットを追加することです。大きなテキストフィールドを使用するために、デフォルトの<textarea>の代わりにRichTextEditorWidgetを使いたいとしましょう。この場合、以下のように記述します。from django.contrib import admin from django.db import models # Import our custom widget and our model from where they're defined from myapp.models import MyModel from myapp.widgets import RichTextEditorWidget class MyModelAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {"widget": RichTextEditorWidget}, }
ディクショナリ内のキーは文字列 ではなく 実際のフィールドクラスである点に注意してください。値は別のディクショナリです; これらの引数はフォームフィールドの
__init__()メソッドに渡されます。詳細は フォーム API を参照してください。警告
リレーションフィールド (例えば
ForeignKeyやManyToManyField) でカスタムウィジェットを使用したいときは、,raw_id_fields、radio_fields、autocomplete_fieldsにそのフィールドの名前を含まないようにしてください。formfield_overridesは、raw_id_fields、radio_fields、autocomplete_fieldsのどれかがセットされたリレーションフィールドのウィジェットは変更しません。これは、raw_id_fields、radio_fields、autocomplete_fieldsの 3 つがこれら自身のカスタムウィジェットを暗示するからです。
- ModelAdmin.inlines¶
後述の
InlineModelAdminオブジェクトとModelAdmin.get_formsets_with_inlines()を参照してください。
- ModelAdmin.list_display¶
admin のチェンジリストページでどのフィールドを表示するかコントロールするために、
list_displayをセットします。実装例:
list_display = ["first_name", "last_name"]
list_displayをセットしない場合、admin サイトは各オブジェクトの__str__()表現を表示する単一の列を表示します。list_displayで使用できる値は5種類あります。最も簡単なもの以外は、フィールドの表示方法をカスタマイズするためにdisplay()デコレーターを使用できます。モデルフィールドの名前。次に例を示します。
class PersonAdmin(admin.ModelAdmin): list_display = ["first_name", "last_name"]
リレーション先フィールドの名前を
__表記で記述します。例えば、次のようにします。class PersonAdmin(admin.ModelAdmin): list_display = ["city__name"]
1 つの引数 (モデルのインスタンス) を受け入れる呼び出し可能オブジェクトです。次に例を示します。
@admin.display(description="Name") def upper_case_name(obj): return f"{obj.first_name} {obj.last_name}".upper() class PersonAdmin(admin.ModelAdmin): list_display = [upper_case_name]
1 つの引数 (モデルのインスタンス) を受け入れる
ModelAdminメソッドを表す文字列です。次に例を示します。class PersonAdmin(admin.ModelAdmin): list_display = ["upper_case_name"] @admin.display(description="Name") def upper_case_name(self, obj): return f"{obj.first_name} {obj.last_name}".upper()
モデルの属性や (必須の引数を持たない) メソッドを表す文字列です。次に例を示します。
from django.contrib import admin from django.db import models class Person(models.Model): name = models.CharField(max_length=50) birthday = models.DateField() @admin.display(description="Birth decade") def decade_born_in(self): decade = self.birthday.year // 10 * 10 return f"{decade}’s" class PersonAdmin(admin.ModelAdmin): list_display = ["name", "decade_born_in"]
Changed in Django 5.1:関連フィールドを対象にする際に
__ルックアップを使用するサポートが追加されました。list_displayに関する特殊な状況の注意点があります。フィールドが
ForeignKeyの場合、 Django はリレーション先オブジェクトの__str__()を表示します。ManyToManyFieldフィールドは、テーブル内で各行に対して個別の SQL ステートメントを実行する可能性があるため、サポートされていません。それでも使いたい場合は、モデルにカスタムメソッドを作成し、そのメソッドの名前をlist_displayに追加してください。 (list_display内でのカスタムメソッドについてより詳しくは下記を参照してください。)フィールドが
BooleanFieldの場合、Django はTrue,False,Noneの代わりに、かわいい "yes", "no", "unknown" アイコンを表示します。与えられた文字列がモデル、
ModelAdmin、呼び出し可能オブジェクトのどれかの場合、Django はデフォルトで HTML エスケープして出力します。ユーザーの入力をエスケープしたり非エスケープのタグを使う場合、format_html()を使用してください。以下は、モデルの例です。
from django.contrib import admin from django.db import models from django.utils.html import format_html 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) @admin.display def colored_name(self): return format_html( '<span style="color: #{};">{} {}</span>', self.color_code, self.first_name, self.last_name, ) class PersonAdmin(admin.ModelAdmin): list_display = ["first_name", "last_name", "colored_name"]
これまでの例で見てきたように、呼び出し可能オブジェクト、モデルメソッド、または
ModelAdminメソッドを使用する場合、display()デコレータで呼び出し可能オブジェクトをラップし、description引数を渡すことで、カラムのタイトルをカスタマイズできます。フィールドの値が
None、空の文字列、エレメントを持たない iterable のいずれかの場合、Django は-(ダッシュ) を表示します。この挙動はAdminSite.empty_value_displayでオーバーライドできます。from django.contrib import admin admin.site.empty_value_display = "(None)"
ModelAdmin.empty_value_displayも使用できます。class PersonAdmin(admin.ModelAdmin): empty_value_display = "unknown"
もしくは、フィールドレベルで以下のようにできます。
class PersonAdmin(admin.ModelAdmin): list_display = ["name", "birth_date_view"] @admin.display(empty_value="unknown") def birth_date_view(self, obj): return obj.birth_date
与えられた文字列がモデル
ModelAdminのメソッドか、True,False,Noneを返す呼び出し可能オブジェクトの場合、 Django はそのメソッドをdisplay()デコレータでラップし、boolean引数をTrueで渡すと、かわいい "yes", "no", "unknown" アイコンを表示します。from django.contrib import admin from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) birthday = models.DateField() @admin.display(boolean=True) def born_in_fifties(self): return 1950 <= self.birthday.year < 1960 class PersonAdmin(admin.ModelAdmin): list_display = ["name", "born_in_fifties"]
__str__()メソッドは、他のモデルメソッドとまったく同様にlist_display内でも有効です。つまり、以下のような書き方は完璧に OK です。list_display = ["__str__", "some_other_field"]
通常、実際のデータベースフィールドではない
list_displayの要素は、ソートに使用できません (Django のソートはすべてデータベースレベルで実行されるためです)。しかし、
list_displayの要素が特定のデータベースフィールドを表す場合、メソッドにdisplay()デコレータを使用し、ordering引数を渡すことで、その事実を伝えることができます。from django.contrib import admin from django.db import models from django.utils.html import format_html class Person(models.Model): first_name = models.CharField(max_length=50) color_code = models.CharField(max_length=6) @admin.display(ordering="first_name") def colored_first_name(self): return format_html( '<span style="color: #{};">{}</span>', self.color_code, self.first_name, ) class PersonAdmin(admin.ModelAdmin): list_display = ["first_name", "colored_first_name"]
上記のコードは、admin 内で
colored_first_nameで ソートしようとするとき、first_nameフィールドで並べ替えるよう Django に伝えます。引数
orderingで降順を示すには、フィールド名の前にハイフンをつけます。上記の例を使うと、次のようになります。@admin.display(ordering="-first_name") def colored_first_name(self): ...
引数
Lorderingはリレーション先モデルの値でソートするクエリのルックアップをサポートします。この例では、"author first name" カラムをリストに表示し、first name でソートできるようにしています。class Blog(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey(Person, on_delete=models.CASCADE) class BlogAdmin(admin.ModelAdmin): list_display = ["title", "author", "author_first_name"] @admin.display(ordering="author__first_name") def author_first_name(self, obj): return obj.author.first_name
クエリ式 は
ordering引数と一緒に使うことができます。from django.db.models import Value from django.db.models.functions import Concat class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) @admin.display(ordering=Concat("first_name", Value(" "), "last_name")) def full_name(self): return self.first_name + " " + self.last_name
list_displayの要素はプロパティにすることもできます。class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) @property @admin.display( ordering="last_name", description="Full name of the person", boolean=False, ) def full_name(self): return self.first_name + " " + self.last_name class PersonAdmin(admin.ModelAdmin): list_display = ["full_name"]
ただし、
@propertyは@displayより上でなければなりません。display()デコレータを使用するのではなく、直接表示関連の属性を設定する古い方法を使用している場合は、@propertyデコレータではなく、property()関数を使用しなければならないことに注意してください。def my_property(self): return self.first_name + " " + self.last_name my_property.short_description = "Full name of the person" my_property.admin_order_field = "last_name" my_property.boolean = False full_name = property(my_property)
list_displayのフィールド名はHTMLの出力でも<th>要素にcolumn-<field_name>という形でCSSクラスとして表示されます。これは例えばCSSファイルでカラムの幅を設定するのに使うことができます。Django は、
list_displayの各要素を以下の順番で解釈しようとします。モデルのフィールド、またはリレーション先のフィールド由来のフィールド。
呼び出し可能オブジェクト。
ModelAdmin属性を表す文字列。モデル属性を表す文字列。
たとえば、
first_nameがモデルフィールドとModelAdmin属性の両方で存在する場合、モデルフィールドの方が使用されます。
- ModelAdmin.list_display_links¶
list_display内のフィールドにおいて "変更" ページへのリンクをコントロールするには、list_display_linksを使用してください。デフォルトでは、チェンジリストページは最初のカラム (
list_displayで最初に指定したフィールド) に各アイテムの変更ページへのリンクが貼られています。しかし、list_display_linksを使って変更できます。リンクを貼らない場合は
Noneをセットしてください。(
list_displayと同様のフォーマットで) リンクに変換したいカラムのフィールドのリストないしタプルをセットしてください。1 つないし複数のフィールドを指定できます。
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"]
以下の例では、チェンジリストページのグリッドにはリンクがなくなります。
class AuditEntryAdmin(admin.ModelAdmin): list_display = ["timestamp", "message"] list_display_links = None
- ModelAdmin.list_editable¶
チェンジリストページ上での編集を有効にしたいモデルのフィールド名のリストを
list_editableにセットしてください。list_editableに指定されたフィールドは、チェンジリストページ上でフォームウィジェットとして表示され、ユーザーは複数の行を一度に編集して保存できます。注釈
list_editableは、他のオプションと特定部分で相互関係にあります。以下のルールに注意してください。list_editable内のすべてのフィールドはlist_displayに含まれている必要があります。表示されていないフィールドは編集できないのです!list_editableとlist_display_linksに同じフィールドを同時に指定することはできません -- 1 つのフィールドがフォームとリンクの両方になることはできないからです。
これらのルールを破った場合、バリデーションエラーとなります。
- ModelAdmin.list_filter¶
admin のチェンジリストページの右サイドバーのフィルタを有効化するには、
list_filterをセットしてください。最もシンプルな
list_filterはフィルタリングを有効にするフィールド名のリストまたはタプルを受け取りますが、より高度なオプションもいくつか用意されています。詳細は ModelAdmin リストフィルタ を参照してください。
- ModelAdmin.list_max_show_all¶
"Show all" の admin チェンジリストページで表示するアイテム数をコントロールするには、
list_max_show_allをセットしてください。チェンジリストページの "Show all" リンクは、この設定値以下の場合のみ表示されます。デフォルトでは200にセットされています。
- ModelAdmin.list_per_page¶
ページ分割された admin のチェンジリストページに表示するアイテム数をコントロールするには、
list_per_pageをセットしてください。デフォルトでは100にセットされています。
admin のチェンジリストページでオブジェクトのリストを検索するときに
select_related()を使用するよう Django に伝えるには、list_select_relatedをセットしてください。これにより多くのデータベースクエリを削減できます。値は真偽値、リスト、タプルのどれかでなければなりません。デフォルトは
Falseです。値が
Trueのとき、常にselect_related()が呼ばれます。Falseのときは、ForeignKeyが存在する場合 Django はlist_displayを参照してselect_related()を呼び出します。よりきめ細やかにコントロールする場合は、
list_select_relatedの値にタプル (ないしリスト) を使用してください。空のタプルは、Django がselect_relatedを一切呼び出さないようにします。他のタプルは、パラメータとして直接select_relatedに渡されます。次に例を示します。class ArticleAdmin(admin.ModelAdmin): list_select_related = ["author", "category"]
これは
select_related('author', 'category')を呼び出します。リクエストに基づいた動的な値を指定する場合は、
get_list_select_related()メソッドを実装できます。注釈
ModelAdminはselect_related()がチェンジリストのQuerySetで既に呼び出されていた場合、この属性を無視します。
- ModelAdmin.ordering¶
Django の admin ビューでオブジェクトのリストをどのようにソートするかを指定するには、
orderingをセットしてください。モデルのorderingパラメータと同じフォーマットでリストかタプルを与えてください。指定がない場合、Django admin はモデルのデフォルトの並び順を使用します。
動的なソートを指定する場合 (例えばユーザーや言語に応じて変更する場合など)、
get_ordering()メソッドを実装できます。並べ替えやソートに伴うパフォーマンス上の注意
全体のソートのための単一もしくは unique together フィールド指定をチェンジリストが見つけられない場合、チェンジリストは
pkをチェンジリストに追加します。これは結果の決定論的なソートを保証するためです。たとえば、デフォルトのソートが一意でない
nameフィールドによって実行される場合、チェンジリストはnameとpkでソートされます。テーブルのレコード数が多く、nameとpkのインデックスがない場合は、パフォーマンスの低下を招きます。
- ModelAdmin.paginator¶
ページ分割に使われる paginator クラスです。デフォルトでは
django.core.paginator.Paginatorが使われます。カスタムの paginator クラスがdjango.core.paginator.Paginatorと同じコンストラクタインターフェースを持たない場合、ModelAdmin.get_paginator()に対する実装も行う必要があります。
- ModelAdmin.prepopulated_fields¶
prepopulated_fieldsを、フィールド名と事前入力するフィールドをマッピングした辞書に設定します。class ArticleAdmin(admin.ModelAdmin): prepopulated_fields = {"slug": ["title"]}
設定された場合、指定されたフィールドは割り当てられたフィールドから入力するために JavaScript を使用します。この機能の主な用途は、1つ以上の他のフィールドから
SlugFieldフィールドの値を自動的に生成することです。生成される値はソースフィールドの値を連結し、その結果を有効なスラグに変換することで生成されます (たとえば、ダッシュをスペースに置き換えたり、ASCII 文字を小文字にしたりします)。事前入力されたフィールドは値が保存された後に JavaScript によって変更されることはありません。通常、スラグが変更されることは望ましくありません (スラグがオブジェクトで使用されている場合、オブジェクトの URL が変更されることになります)。
prepopulated_fieldsはDateTimeField、ForeignKey、OneToOneField、ManyToManyFieldフィールドを受け入れません。
- ModelAdmin.preserve_filters¶
デフォルトでは、オブジェクトを作成、編集、削除しても、適用されたフィルタはリストビューに保存されます。この属性を
Falseに設定することで、フィルタをクリアできます。
- ModelAdmin.show_facets¶
管理画面のチェンジリストのフィルタにファセット数を表示するかどうかを制御します。デフォルトは
ShowFacets.ALLOWです。表示されている場合、ファセット数は現在適用されているフィルタに合わせて更新されます。
- class ShowFacets¶
ModelAdmin.show_facetsに指定できる値の Enum。- ALWAYS¶
常にファセット数を表示します。
- ALLOW¶
クエリ文字列パラメータ
_facetsが指定された場合に、ファセット数を表示します。
- NEVER¶
ファセット数を表示しません。
show_facetsに必要なShowFacetsの値を指定します。例えば、クエリパラメータを指定することなく常にファセット数を表示したい場合:from django.contrib import admin class MyModelAdmin(admin.ModelAdmin): ... # Have facets always shown for this model admin. show_facets = admin.ShowFacets.ALWAYS
ファセットを使う場合のパフォーマンス上の注意
ファセットフィルタを有効にすると、管理画面のチェンジリストページのクエリ数がフィルタの数だけ増えます。これらのクエリは、特に大きなデータセットの場合、パフォーマンスの問題を引き起こすかもしれません。このような場合は、
show_facetsをShowFacets.NEVERに設定して、ファセットを完全に無効にするのが適切でしょう。
- ModelAdmin.radio_fields¶
デフォルトでは、
ForeignKeyやchoicesがセットされたフィールドに対して、Django の admin はセレクトボックスのインターフェース (<select>) を使用します。フィールドがradio_fieldsに指定された場合、Django は代わりに ラジオボタンのインターフェースを使用します。groupがPersonモデルのForeignKeyだと仮定すると、次のようになります。class PersonAdmin(admin.ModelAdmin): radio_fields = {"group": admin.VERTICAL}
django.contrib.adminモジュールからHORIZONTALかVERTICALのどちらを使用するか選択してください。ForeignKeyないしchoicesがセットされたフィールド以外は、radio_fieldsに含めないでください。
- ModelAdmin.autocomplete_fields¶
autocomplete_fieldsは、Select2 オートコンプリート入力に変更したいForeignKeyないしManyToManyFieldフィールドのリストです。デフォルトでは、これらのフィールドに対して admin はセレクトボックスのインターフェース (
<select>) を使用します。ドロップダウン内に表示する関係インスタンスをすべて選択するオーバーヘッドから逃れたいこともあるでしょう。Select2 入力はデフォルトの入力と似た見た目ですが、非同期的にオプションを読み込む検索機能を持っています。こちらの方が高速で、特に関係モデルに多くのインスタンスがある場合にはユーザーフレンドリーです。
オートコンプリート検索はリレーション先オブジェクトの
ModelAdminを使用するため、ModelAdminにsearch_fieldsを定義する必要があります。認可されていないデータが漏洩されるのを防ぐため、オートコンプリートを使うには、ユーザーは必ずリレーション先オブジェクトに対する
viewかchange権限を持っていなければなりません。結果のソートおよびページ分割は、関係する
ModelAdminのget_ordering()とget_paginator()メソッドでコントロールします。以下の例では、
ChoiceAdminフィールドはQuestionへのForeignKeyに対するオートコンプリートフィールドを持ちます。結果はquestion_textフィールドによりフィルタされ、またdate_createdフィールドにより並べ替えられます:class QuestionAdmin(admin.ModelAdmin): ordering = ["date_created"] search_fields = ["question_text"] class ChoiceAdmin(admin.ModelAdmin): autocomplete_fields = ["question"]
巨大なデータセットに対するパフォーマンス上の注意
ModelAdmin.orderingを使った並べ替えは、巨大なクエリセットは遅くなるため、パフォーマンスの問題の原因となります。また、検索フィールドがデータベースによるインデックス化がされていないフィールドを含む場合、巨大なテーブルでは貧弱なパフォーマンスしか発揮できなくなってしまいます。
このような場合は、フルテキストのインデックスサーチを使用した独自の
ModelAdmin.get_search_results()実装を記述するのがよいでしょう。また、デフォルトの paginator は常に
count()を発行するため、巨大なテーブルではPaginatorを変更するのがお勧めです。例えば、Paginator.countプロパティのデフォルトの実装をオーバーライドできます。
- ModelAdmin.raw_id_fields¶
デフォルトでは、
ForeignKeyのフィールドに対して Django の admin はセレクトボックスのインターフェース (<select>) を使用します。ドロップダウン内に表示する関係インスタンスをすべて選択するオーバーヘッドから逃れたいこともあるでしょう。raw_id_fieldsは、ForeignKeyやManyToManyFieldに対するInputウィジェットを適用したいフィールドのリストです:class ArticleAdmin(admin.ModelAdmin): raw_id_fields = ["newspaper"]
raw_id_fieldsInputウィジェットには、ForeignKeyの場合はプライマリキーを、ManyToManyFieldの場合はカンマで区切った値のリストを入力します。raw_id_fieldsウィジェットには、ユーザーが値を検索および選択できるよう、隣にルーペボタンがあります:
- ModelAdmin.readonly_fields¶
デフォルトでは、すべてのフィールドが編集可能となっています。このオプションに含まれるフィールド (
listかtupleで指定します) は、データをそのまま表示するだけで編集できなくなります。また、追加と編集に使われるModelFormからも除外されます。ModelAdmin.fieldsかModelAdmin.fieldsetsを指定した場合、read-only のフィールドは表示のために存在している必要があります (存在しなければ無視されます)。ModelAdmin.fieldsやModelAdmin.fieldsetsで明示的に並び順を定義しないでreadonly_fieldsを使った場合、これらのフィールドはすべての編集可能なフィールドの後に表示されます。read-only のフィールドはモデルのフィールドからデータを表示するだけではなく、モデルや
ModelAdminクラス自身のメソッドの出力を表示させることもできます。これはModelAdmin.list_displayの挙動に似ています。これにより、編集中のオブジェクトのステータスのフィードバックを admin インターフェースに与えることができるようになります。たとえば:from django.contrib import admin from django.utils.html import format_html_join from django.utils.safestring import mark_safe class PersonAdmin(admin.ModelAdmin): readonly_fields = ["address_report"] # description functions like a model field's verbose_name @admin.display(description="Address") def address_report(self, instance): # assuming get_full_address() returns a list of strings # for each line of the address and you want to separate each # line by a linebreak return format_html_join( mark_safe("<br>"), "{}", ((line,) for line in instance.get_full_address()), ) or mark_safe("<span class='errors'>I can't determine this address.</span>")
- ModelAdmin.save_as¶
admin のチェンジーフォームで "新規に保存" 機能を有効化するには
save_asをセットしてください。通常、オブジェクトには 3 つの保存オプションがあります: "保存"、"保存して編集を続ける"、"保存して 1 つ追加" です。
save_asがTrueの場合、"保存して 1 つ追加" が "新規に保存" ボタンに変更され、既存のオブジェクトを変更するのではなく (新しい ID) で新規のオブジェクトが作成されるようになります。デフォルトでは
save_asはFalseにセットされています。
- ModelAdmin.save_as_continue¶
save_as=Trueのとき、新規オブジェクトを保存した後のデフォルトのリダイレクト先はそのオブジェクトの変更ビューです。save_as_continue=Falseにセットすると、リダイレクト先がチェンジリストビューになります。デフォルトでは
save_as_continueはTrueにセットされています。
- ModelAdmin.save_on_top¶
admin のチェンジフォームの上部に保存ボタンを追加するには
save_on_topをセットしてください。通常、保存ボタンはフォームの下部のみに表示されます。
save_on_topをセットすると、ボタンは上部と下部の両方に表示されるようになります。デフォルトでは
save_on_topはFalseにセットされています。
- ModelAdmin.search_fields¶
admin のチェンジリストページで検索ボックスを有効化するには
search_fieldsをセットしてください。セットするのはフィールド名のリストで、ここで指定したフィールドはテキストボックス内での検索クエリの対象となります。指定するフィールドの種類は、
CharFieldやTextFieldといったテキストフィールドである必要があります。ルックアップ API の "follow" 記法を使えばForeignKeyやManyToManyFieldをルックアップすることもできます。search_fields = ["foreign_key__related_fieldname"]
たとえば、著者の情報を持つブログエントリーの場合、以下の定義により、著者のメールアドレスによるブログエントリーの検索が可能となります。
search_fields = ["user__email"]
検索ボックスで検索が行われるとき、Django は検索クエリを単語に分割し、(
icontainsルックアップを使って) 大文字と小文字を区別しない各単語を含むオブジェクトを返します。各単語は最低 1 つのsearch_fieldsに含まれている必要があります。例えば、search_fieldsが['first_name', 'last_name']にセットされ、ユーザーがjohn lennonと検索した場合、Django は SQL のWHERE節と同等の検索を実行します。WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
検索クエリには空白を含む引用句を含めることができます。たとえば、ユーザが
"john winston"や'john winston'を検索した場合、 Django はこの SQL のWHERE句と等価な処理を行います。WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')
もし
icontainsルックアップを使用したくない場合は、フィールドに追加することで任意のルックアップを使用できます。例えば、search_fieldsを['first_name__exact']に設定することで、exactを使用できます。いくつかの (古い) ショートカットを使って、フィールドルックアップを指定することもできます。以下の文字で
search_fields内のフィールドにプレフィックスを追加できます。これはフィールドに__<lookup>を追加するのと同等です。プレフィックス
ルックアップ
^
=
@
None
検索方法をカスタムする必要がある場合は、
ModelAdmin.get_search_results()を使って追加的もしくは代替の検索方法を提供できます。
- ModelAdmin.search_help_text¶
search_help_textには検索ボックスの下に表示される説明文を指定します。
- ModelAdmin.show_full_result_count¶
フィルタリングされた admin ページにオブジェクトのカウント (例:
99 results (103 total)) を表示するかどうかをコントロールするには、show_full_result_countをセットしてください。Falseにセットすると、代わりに99 results (Show all)のような文字列が表示されるようになります。デフォルトの
show_full_result_count=Trueは、テーブル内の全アイテムをカウントするクエリを発行するため、多くの行を含むテーブルではパフォーマンス低下の原因となります。
- ModelAdmin.sortable_by¶
デフォルトでは、チェンジリストページでは
list_displayで指定された全てのモデルフィールド (およびdisplay()デコレータのordering引数を使用する呼び出し可能オブジェクト、またはadmin_order_field属性を持つ呼び出し可能オブジェクト) によるソートが可能です。特定のカラムでのソートを無効化したい場合、
sortable_byにlist_displayサブセットのコレクション (例:list、tuple、set) をセットしてください。空のコレクションを指定すると、すべてのカラムでソート不可となります。リストを動的に指定する必要があるときは、代わりに
get_sortable_by()メソッドを実装してください。
- ModelAdmin.view_on_site¶
"サイトで見る" リンクを表示するか否かをコントロールするには、
view_on_siteをセットしてください。このリンクは保存されたオブジェクトを表示できる URL に誘導します。値は、真偽値か呼び出し可能オブジェクトで指定します。
True(デフォルトです) の場合、オブジェクトのget_absolute_url()メソッドが使われ、URLが生成されます。モデルが
get_absolute_url()メソッドを持っていても "サイトで見る" ボタンを表示したくない場合は、view_on_siteにFalseをセットしてください:from django.contrib import admin class PersonAdmin(admin.ModelAdmin): view_on_site = False
呼び出し可能オブジェクトの場合、引数にモデルのインスタンスを受け入れます。例えば:
from django.contrib import admin from django.urls import reverse class PersonAdmin(admin.ModelAdmin): def view_on_site(self, obj): url = reverse("person-detail", kwargs={"slug": obj.slug}) return "https://example.com" + url
カスタムテンプレートのオプション¶
admin テンプレートをオーバーライドする セクションでは、デフォルトの admin テンプレートをオーバーライドないし拡張する方法を説明しています。ModelAdmin ビューで使用されるデフォルトのテンプレートをオーバーライドするには、以下のオプションを使用してください:
- ModelAdmin.add_form_template¶
カスタムンテンプレートの絶対パスで、
add_view()で使われます。
- ModelAdmin.change_form_template¶
カスタムンテンプレートの絶対パスで、
change_view()で使われます。
- ModelAdmin.change_list_template¶
カスタムンテンプレートの絶対パスで、
changelist_view()で使われます。
- ModelAdmin.delete_confirmation_template¶
カスタムンテンプレートの絶対パスで、1 つ以上のオブジェクトを削除するときに確認ページを表示するために、
delete_view()で使われます。
- ModelAdmin.delete_selected_confirmation_template¶
カスタムンテンプレートの絶対パスで、1 つ以上のオブジェクトを削除するときに確認ページを表示するために、
delete_selectedアクションメソッドで使われます。アクションのドキュメント を参照してください。
- ModelAdmin.object_history_template¶
カスタムンテンプレートの絶対パスで、
history_view()で使われます。
- ModelAdmin.popup_response_template¶
カスタムンテンプレートの絶対パスで、
response_add()、response_change()、response_delete()の 3 つで使われます。
ModelAdmin のメソッド¶
警告
ModelAdmin.save_model() や ModelAdmin.delete_model() をオーバーライドするときは、オブジェクトの保存や削除の処理を記述する必要があります。これは、制限を設けるためではなく、追加的な操作を可能にするための仕様です。
- ModelAdmin.save_model(request, obj, form, change)[ソース]¶
save_modelメソッドには、HttpRequest、モデルのインスタンス、ModelFormのインスタンス、追加か変更かを表す真偽値が渡されます。このメソッドをオーバーライドすると、保存の前後に操作を追加できます。super().save_model()を呼び出して、Model.save()を使ってオブジェクトを保存してください。例えば、保存前にオブジェクトに
request.userを追加するには:from django.contrib import admin class ArticleAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.user = request.user super().save_model(request, obj, form, change)
- ModelAdmin.delete_model(request, obj)[ソース]¶
delete_modelには、HttpRequestとモデルのインスタンスが渡されます。このメソッドをオーバーライドすると、削除の前後に操作を追加できます。super().delete_model()を呼び出して、Model.delete()を使ってオブジェクトを削除してください。
- ModelAdmin.delete_queryset(request, queryset)[ソース]¶
delete_queryset()には、HttpRequestと削除するオブジェクトのQuerySetが渡されます。このメソッドをオーバーライドすると、"選択したオブジェクトの削除" アクション に対する削除のプロセスをカスタムできます。
- ModelAdmin.save_formset(request, form, formset, change)[ソース]¶
save_formsetメソッドには、HttpRequest、親ModelFormのインスタンス、親オブジェクトの追加か変更かを表す真偽値が与えられます。たとえば、変更のあったフォームセットのモデルのインスタンスそれぞれに
request.userを追加するには、次のようにします。class ArticleAdmin(admin.ModelAdmin): def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) for obj in formset.deleted_objects: obj.delete() for instance in instances: instance.user = request.user instance.save() formset.save_m2m()
関連項目: フォームセット内のオブジェクトを保存する
警告
ModelAdmin プロパティを返すすべてのフックは、その値のコピーではなく、プロパティ自体を返します。動的に値を変更すると、予期しない結果を招くことがあります。
ModelAdmin.get_readonly_fields() を例に取ってみましょう。
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ["name"]
def get_readonly_fields(self, request, obj=None):
readonly = super().get_readonly_fields(request, obj)
if not request.user.is_superuser:
readonly.append("age") # Edits the class attribute.
return readonly
これにより、readonly_fields は ["name", "age", "age", ...] となり、スーパーユーザーであっても、非スーパーユーザーがページを訪れるたびに "age" が追加されることになります。
- ModelAdmin.get_ordering(request)¶
get_orderingメソッドは引数にrequestを取り、orderingのときと同じようなlistかtupleを返すことが期待されます。次に例を示します。class PersonAdmin(admin.ModelAdmin): def get_ordering(self, request): if request.user.is_superuser: return ["name", "rank"] else: return ["name"]
- ModelAdmin.get_search_results(request, queryset, search_term)[ソース]¶
get_search_resultsメソッドは、検索語と一致するオブジェクトを表示するための、オブジェクトのリストを修正します。リクエスト、現在のフィルタを適用するクエリセット、 ユーザーが入力した検索語を受け取ります。 検索を実行するために修正されたクエリセットと、結果に重複があるかどうかを表す真偽値を含むタプルを返します。デフォルトの実装では、
ModelAdmin.search_fieldsに含まれるフィールドを検索します。このメソッドは、独自の検索方法でオーバーライドできます。例えば、数値のフィールドで検索したり、Solr や Haystack といった外部のツールを使うことができます。独自の検索方法によって実装されたクエリセットの変更が結果に重複を生じさせるかを確認し、返値の 2 番目の要素に
Trueを返す必要があります。たとえば、
nameとageで検索するには、以下のように使います。class PersonAdmin(admin.ModelAdmin): list_display = ["name", "age"] search_fields = ["name"] def get_search_results(self, request, queryset, search_term): queryset, may_have_duplicates = super().get_search_results( request, queryset, search_term, ) try: search_term_as_int = int(search_term) except ValueError: pass else: queryset |= self.model.objects.filter(age=search_term_as_int) return queryset, may_have_duplicates
この実装は、数値フィールドに対して文字列比較を行う
search_fields = ('name', '=age')に比べて、はるかに効率的です... たとえば PostgreSQL では... OR UPPER("polls_choice"."votes"::text) = UPPER('4')となります。
save_relatedメソッドには、HttpRequest、親ModelFormのインスタンス、インラインフォームセットのリスト、親の追加か変更かを表す真偽値が与えられます。このメソッドで、保存の前後に親に対するリレーション先オブジェクトに対する操作を追加できます。この時点では親オブジェクトとそのフォームはすでに保存されていることに注意してください。
- ModelAdmin.get_autocomplete_fields(request)¶
get_autocomplete_fields()メソッドには、HttpRequestが渡され、上述のModelAdmin.autocomplete_fieldsセクションで説明した通りオートコンプリートウィジェットで表示するフィールドの名前のlistかtupleを返すことが期待されます。
- ModelAdmin.get_readonly_fields(request, obj=None)¶
get_readonly_fieldsメソッドには、HttpRequestと編集対象のobj(ないし新規追加用のNone) が渡され、上述のModelAdmin.readonly_fieldsセクションで説明した通り、読み取り専用で表示するフィールドの名前のlistかtupleを返すことが期待されます。
- ModelAdmin.get_prepopulated_fields(request, obj=None)¶
get_prepopulated_fieldsメソッドには、HttpRequestと編集対象のobj(ないし新規追加用のNone) が渡され、上述のModelAdmin.prepopulated_fieldsセクションで説明した通りdictionaryを返すことが期待されます。
- ModelAdmin.get_list_display(request)[ソース]¶
get_list_displayメソッドには、HttpRequestが渡され、上述のModelAdmin.list_displayセクションで説明した通りチェンジリストビューで表示するフィールドの名前のlistかtupleを返すことが期待されます。
- ModelAdmin.get_list_display_links(request, list_display)[ソース]¶
get_list_display_linksメソッドには、HttpRequestとModelAdmin.get_list_display()によって返されたlistないしtupleが渡されます。上述のModelAdmin.list_display_linksセクションで説明した通り、チェンジリストで変更ビューにリンクを貼りたいフィールドの名前のlistかtuple、もしくはNoneを返すことが期待されます。
- ModelAdmin.get_exclude(request, obj=None)¶
get_excludeメソッドには、HttpRequestと編集対象のobj(ないし新規追加用のNone) が渡され、上述のModelAdmin.excludeセクションで説明した通りフィールドのリストを返すことが期待されます。
- ModelAdmin.get_fields(request, obj=None)¶
get_fieldsメソッドには、HttpRequestと編集対象のobj(ないし新規追加用のNone) が渡され、上述のModelAdmin.fieldsセクションで説明した通りフィールドのリストを返すことが期待されます。
- ModelAdmin.get_fieldsets(request, obj=None)¶
get_fieldsetsメソッドには、HttpRequestと編集対象のobj(ないし新規追加用のNone) が渡され、2 値タプルのリストを返すことが期待されます。各 2 値タプルは、上述のModelAdmin.fieldsetsセクションで説明した通り admin のフォームページ上の<fieldset>を表します。
- ModelAdmin.get_list_filter(request)[ソース]¶
get_list_filterメソッドには、HttpRequestが渡され、list_filter属性のときと同じ種類のシーケンス型を返すことが期待されます。
get_list_select_relatedメソッドには、HttpRequestが渡され、真偽値もしくはModelAdmin.list_select_relatedと同様のリストを返す必要があります。
- ModelAdmin.get_search_fields(request)[ソース]¶
get_search_fieldsメソッドには、HttpRequestが渡され、search_fields属性のときと同じ種類のシーケンス型を返すことが期待されます。
- ModelAdmin.get_sortable_by(request)¶
get_list_displayメソッドはHttpRequestを受け取り、チェンジリストページでソート可能なフィールドの名のコレクション (例:list、tuple、set) を返すことが期待されます。デフォルトの実装では、セットされている場合は
sortable_byを返します。セットされていなければget_list_display()を参照します。たとえば、1 つ以上のカラムを並び替え不可にするには:
class PersonAdmin(admin.ModelAdmin): def get_sortable_by(self, request): return {*self.get_list_display(request)} - {"rank"}
- ModelAdmin.get_inline_instances(request, obj=None)[ソース]¶
get_inline_instancesメソッドは、編集中のHttpRequestとobj(追加フォームの場合はNone) を受け取り、以下のInlineModelAdminセクションで説明されているように、InlineModelAdminオブジェクトのlistまたはtupleを返すことが期待されます。例えば、以下は追加、変更、削除、閲覧の権限に基づくデフォルトのフィルタリングなしでインラインを返す方法です:class MyModelAdmin(admin.ModelAdmin): inlines = [MyInline] def get_inline_instances(self, request, obj=None): return [inline(self.model, self.admin_site) for inline in self.inlines]
このメソッドをオーバーライドする場合、返値となるインラインは
inlinesで定義したクラスのインスタンスにしてください。間違えると、リレーション先オブジェクトを追加する際に "Bad Request" が発生する可能性があります。
- ModelAdmin.get_inlines(request, obj)¶
get_inlinesメソッドは、編集対象のHttpRequestとobj(追加フォームの場合はNone) を受け取り、インラインのイテラブルを返すことが期待されます。ModelAdmin.inlinesで指定する代わりに、このメソッドをオーバーライドすることで、リクエストやモデルインスタンスに基づいて動的にインラインを追加できます。
- ModelAdmin.get_urls()[ソース]¶
ModelAdminのget_urlsメソッドは URLconf と同じようにその ModelAdmin で使用する URL を返します。 そのため、 URL ディスパッチャ で説明されているように、ビューのAdminSite.admin_view()ラッパーを使って拡張できます:from django.contrib import admin from django.template.response import TemplateResponse from django.urls import path class MyModelAdmin(admin.ModelAdmin): def get_urls(self): urls = super().get_urls() my_urls = [path("my_view/", self.admin_site.admin_view(self.my_view))] return my_urls + urls def my_view(self, request): # ... context = dict( # Include common variables for rendering the admin template. self.admin_site.each_context(request), # Anything else you want in the context... key=value, ) return TemplateResponse(request, "sometemplate.html", context)
admin のレイアウトを使用したい場合、
admin/base_site.htmlを extend してください:{% extends "admin/base_site.html" %} {% block content %} ... {% endblock %}
注釈
self.my_view関数がself.admin_site.admin_viewでラップされていることに注意してください。これは重要であり、次の2つのことを保証します:パーミッションチェックが実行され、アクティブなスタッフユーザーだけがビューにアクセスできるようにします。
django.views.decorators.cache.never_cache()デコレータはキャッシュを防ぐために適用され、返される情報が最新であることを保証します。
注釈
カスタムパターンが通常の管理URLよりも 前に 含まれていることに注意してください。管理URLのパターンは非常に許容範囲が広く、ほぼ何でも一致するため、通常はカスタムURLを組み込みのURLに前置したいと思うでしょう。
この例では、
my_viewは/admin/myapp/mymodel/my_view/にアクセスされます (管理画面の URL が/admin/に含まれていると仮定します)。ページがキャッシュ可能で、それでもパーミッションチェックを行いたい場合は、
AdminSite.admin_view()にcacheable=True引数を渡します:path("my_view/", self.admin_site.admin_view(self.my_view, cacheable=True))
ModelAdminビューはmodel_admin属性を持ちます。その他のAdminSiteビューはadmin_site属性を持ちます。
- ModelAdmin.get_form(request, obj=None, **kwargs)[ソース]¶
admin の追加と変更のビューで使うための
ModelFormクラスを返します。add_view()とchange_view()を参照してください。基本の実装は
modelform_factory()を使用してformをサブクラス化し、fieldsやexcludeといった属性によって修正されます。なので、例えばスーパーユーザーに対して追加的なフィールドを与えたい場合は、以下のように基本のフォームを変更できます:class MyModelAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): if request.user.is_superuser: kwargs["form"] = MySuperuserForm return super().get_form(request, obj, **kwargs)
ModelFormクラスを直接返すこともできます。
- ModelAdmin.get_formsets_with_inlines(request, obj=None)[ソース]¶
admin の追加や変更のビューで使用するための (
FormSet,InlineModelAdmin) ペアを生成します。たとえば、変更ビューのみで特定のインラインを表示したい場合、以下のように
get_formsets_with_inlinesをオーバーライドできます。class MyModelAdmin(admin.ModelAdmin): inlines = [MyInline, SomeOtherInline] def get_formsets_with_inlines(self, request, obj=None): for inline in self.get_inline_instances(request, obj): # hide MyInline in the add view if not isinstance(inline, MyInline) or obj is not None: yield inline.get_formset(request, obj), inline
- ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)¶
ModelAdminのformfield_for_foreignkeyを使うと、ForignKey フィールドに対するデフォルトのフォームフィールドをオーバーライドできます。たとえば、ユーザーに基づいてこの ForeignKey フィールドに対するオブジェクトのサブセットを返すには: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 super().formfield_for_foreignkey(db_field, request, **kwargs)
これは、
HttpRequestインスタンスを使ってCarForeignKey フィールドをフィルタし、特定のUserインスタンスが所有する car のみを表示します。より複雑なフィルタを行うには、
ModelForm.__init__()メソッドを使用することで、モデルのinstanceに基づいたフィルタを行うことができます (リレーションシップを扱うフィールド を参照してください)。たとえば:class CountryAdminForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["capital"].queryset = self.instance.cities.all() class CountryAdmin(admin.ModelAdmin): form = CountryAdminForm
- ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)¶
formfield_for_foreignkeyメソッドと同じように、formfield_for_manytomanyメソッドをオーバーライドすると ManyToMany に対するデフォルトのフォームフィールドを変更できます。たとえば、あるオーナーは複数の car を所有でき、また car は複数のオーナーに所有されるとすると(多対多の関係です)Carのフィールドをフィルタして特定のUserが所有する car だけを表示できます:class MyModelAdmin(admin.ModelAdmin): def formfield_for_manytomany(self, db_field, request, **kwargs): if db_field.name == "cars": kwargs["queryset"] = Car.objects.filter(owner=request.user) return super().formfield_for_manytomany(db_field, request, **kwargs)
- ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)¶
formfield_for_foreignkeyやformfield_for_manytomanyメソッドと同じように、formfield_for_choice_fieldメソッドをオーバーライドすると選択肢として宣言されたフィールドに対するデフォルトのフォームフィールドを変更できます。 たとえば、スーパーユーザーと通常のスタッフで表示する選択肢を違うものにしたい場合、以下のように記述できます:class MyModelAdmin(admin.ModelAdmin): def formfield_for_choice_field(self, db_field, request, **kwargs): if db_field.name == "status": kwargs["choices"] = [ ("accepted", "Accepted"), ("denied", "Denied"), ] if request.user.is_superuser: kwargs["choices"].append(("ready", "Ready for deployment")) return super().formfield_for_choice_field(db_field, request, **kwargs)
choicesの制限フォームフィールドにセットされたすべての
choices属性はそのフォームのフィールドのみに制限されます。モデル上の一致するフィールドに選択肢がセットされている場合、フォームに提供される選択肢はこの選択肢の有効なサブセットでなくてはなりません。そうでない場合、フォームの送信は、モデル自身の保存前のバリデーションでValidationErrorとともに失敗します。
- ModelAdmin.get_changelist(request, **kwargs)[ソース]¶
リスト作成に使われる
Changelistを返します。デフォルトでは、django.contrib.admin.views.main.ChangeListが使われます。このクラスを継承することで、リスト作成の動作を変更できます。
- ModelAdmin.get_changelist_form(request, **kwargs)[ソース]¶
チェンジリストページの
Formsetで使うためのModelFormクラスを返します。カスタムフォームを使うには、たとえば、次のようにします。from django import forms class MyForm(forms.ModelForm): pass class MyModelAdmin(admin.ModelAdmin): def get_changelist_form(self, request, **kwargs): return MyForm
- ModelAdmin.get_changelist_formset(request, **kwargs)[ソース]¶
list_editableを使っている場合、チェンジリストページで使用するための ModelFormSet クラスを返します。カスタムのフォームセットを使うには、たとえば、次のようにします。from django.forms import BaseModelFormSet class MyAdminFormSet(BaseModelFormSet): pass class MyModelAdmin(admin.ModelAdmin): def get_changelist_formset(self, request, **kwargs): kwargs["formset"] = MyAdminFormSet return super().get_changelist_formset(request, **kwargs)
- ModelAdmin.lookup_allowed(lookup, value, request)¶
チェンジリストページのオブジェクトは URL のクエリ文字列からルックアップしてフィルタすることができます。たとえば、
list_filterはその仕組みで動作します。ルックアップはQuerySet.filter()(例user__email=user@example.com) で使われているものと似ています。クエリ文字列のルックアップはユーザによって操作される可能性があるため、無許可のデータ漏洩を防ぐためにサニタイズする必要があります。lookup_allowed()メソッドには、クエリ文字列 ('user__email'など)、対応する値 ('user@example.com'など)、リクエストからのルックアップパスが渡され、パラメータを使用したチェンジリストのQuerySetのフィルタリングが許可されているかどうかを示す真偽値を返します。lookup_allowed()がFalseを返した場合、DisallowedModelAdminLookup(SuspiciousOperationのサブクラス) が発生します。デフォルトでは、
lookup_allowed()はモデルのローカルフィールド、list_filterで使用されるフィールドパス (ただし、get_list_filter()からのパスは使用できません)、limit_choices_toがraw_id_fieldsで正しく機能するために必要なルックアップへのアクセスを許可します。ModelAdminサブクラスで許可されるルックアップをカスタマイズするには、このメソッドをオーバーライドします。
- ModelAdmin.has_view_permission(request, obj=None)¶
objの閲覧が許可されている場合はTrueを、そうでなければFalseを返します。obj がNoneの場合、この種類のオブジェクトの閲覧が一般的に許可されているかどうかを表すよう、TrueかFalseを指定します (たとえば、Falseは現在のユーザーがこの種類のすべてのオブジェクトを閲覧できないことを意味します)。デフォルトの実装では、ユーザーが "change" か "view" 権限を持っていれば
Trueを返します。
- ModelAdmin.has_add_permission(request)¶
オブジェクトの追加が許可されていれば
Trueを、そうでなければFalseを返します。
- ModelAdmin.has_change_permission(request, obj=None)¶
objの編集が許可されている場合はTrueを、そうでなければFalseを返します。objがNoneの場合、この種類のオブジェクトの編集が一般的に許可されているかどうかを表すよう、TrueかFalseを指定します (たとえば、Falseは現在のユーザーがこの種類のすべてのオブジェクトを編集できないことを意味します)。
- ModelAdmin.has_delete_permission(request, obj=None)¶
objの削除が許可されている場合はTrueを、そうでなければFalseを返します。objがNoneの場合、この種類のオブジェクトの削除が一般的に許可されているかどうかを表すよう、TrueかFalseを指定します (たとえば、Falseは現在のユーザーがこの種類のすべてのオブジェクトを削除できないことを意味します)。
- ModelAdmin.has_module_permission(request)¶
admin のインデックスページでモジュールを表示し、そのモジュールへのアクセスを許可する場合は
Trueを、そうでなければFalseを返します。デフォルトではUser.has_module_perms()を使用します。 オーバーライドしても閲覧、追加、変更、削除のアクセス権は制限しません。アクセス権の制限にはhas_view_permission()、has_add_permission()、has_change_permission()、has_delete_permission()を使用してください。
- ModelAdmin.get_queryset(request)¶
ModelAdminのget_querysetメソッドは admin サイトで編集可能なモデルインスタンスのすべてのQuerySetを返します。このメソッドをオーバーライドする場面の 1 つは、ログイン中のユーザーが所有するオブジェクトを表示することです:class MyModelAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super().get_queryset(request) if request.user.is_superuser: return qs return qs.filter(author=request.user)
- ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)[ソース]¶
django.contrib.messagesバックエンドを使ってユーザーにメッセージを送ります。カスタムの ModelAdmin の例 を参照してください。キーワード引数を使うと、メッセージレベルを変更したり、余分な CSS タグを追加したり、
contrib.messageフレームワークがインストールされていない場合にサイレントエラーにしたりすることができます。これらのキーワード引数はdjango.contrib.messages.add_message()の引数と同じです。詳しくはその関数のドキュメントを参照してください。違いの一つは、レベルを整数/定数の他に文字列ラベルとして渡せる点です。
- ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)[ソース]¶
このビューで使用する paginator のインスタンスを返します。デフォルトでは
paginatorのインスタンスを返します。
- ModelAdmin.response_add(request, obj, post_url_continue=None)[ソース]¶
add_view()ステージに対するHttpResponseを決定します。response_addは、admin フォームが送信され、オブジェクトとすべての関係インスタンスが作成および保存された直後に呼び出されます。オーバーライドすることで、オブジェクトが作成された後のデフォルトの動作を変更できます。
- ModelAdmin.response_change(request, obj)[ソース]¶
change_view()ステージに対するHttpResponseを決定します。response_changeは、admin フォームが送信され、オブジェクトとすべての関係インスタンスが保存された直後に呼び出されます。オーバーライドすることで、オブジェクトが変更された後のデフォルトの動作を変更できます。
- ModelAdmin.response_delete(request, obj_display, obj_id)[ソース]¶
delete_view()ステージに対するHttpResponseを決定します。response_deleteは、オブジェクトが削除された後に呼び出されます。オーバーライドすることで、オブジェクトが削除された後のデフォルトの動作を変更できます。obj_displayは削除されたオブジェクトの名前を表す文字列です。obj_idは削除するオブジェクトを取得するために使用するシリアライズされた識別子です。
- ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)[ソース]¶
フォームセットのコンストラクタに渡されるキーワード引数をカスタマイズするためのフックです。たとえばフォームセットのフォームに
requestを渡すには:class MyModelAdmin(admin.ModelAdmin): def get_formset_kwargs(self, request, obj, inline, prefix): return { **super().get_formset_kwargs(request, obj, inline, prefix), "form_kwargs": {"request": request}, }
また、フォームセットのフォームに
initialを指定するためにも使用できます。
- ModelAdmin.get_changeform_initial_data(request)[ソース]¶
admin の変更フォームの初期データに対するフックです。デフォルトでは、フィールドには
GETパラメータで初期値が与えられます。たとえば、?name=initial_valueはnameフィールドの初期値をinitial_valueにセットします。このメソッドは、
{'fieldname': 'fieldval'}という形式のディクショナリを返します:def get_changeform_initial_data(self, request): return {"name": "custom_initial_value"}
- ModelAdmin.get_deleted_objects(objs, request)[ソース]¶
delete_view()と "delete selected" アクション の削除処理をカスタマイズするフックです。引数
objsは削除するオブジェクト (QuerySetまたはモデルインスタンスのリスト) の同型イテラブルで、requestはHttpRequestです。このメソッドは
(deleted_objects, model_count, perms_needed, protected)の4タプルを返さなければなりません。deleted_objectsは削除されるすべてのオブジェクトを表す文字列のリストです。削除されるオブジェクトにリレーション先オブジェクトがある場合、リストはネストされ、それらのリレーション先オブジェクトも含まれます。リストはテンプレート内でunordered_listフィルタを使ってフォーマットされます。model_countは各モデルのverbose_name_pluralと削除されるオブジェクトの数をマッピングした辞書です。perms_needはverbose_nameのセットで、ユーザが削除する権限を持っていないモデルです。protectedは削除できない保護されたリレーション先オブジェクトを表す文字列のリストです。このリストはテンプレートに表示されます。
その他のメソッド¶
- ModelAdmin.add_view(request, form_url='', extra_context=None)[ソース]¶
モデルインスタンスの追加ページに対する Django のビューです。以下のノートを参照してください。
- ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)[ソース]¶
モデルインスタンスの編集ページに対する Django のビューです。以下のノートを参照してください。
- ModelAdmin.changelist_view(request, extra_context=None)[ソース]¶
モデルインスタンスの変更リスト(チェンジリスト)およびアクションページに対する Django のビューです。以下のノートを参照してください。
- ModelAdmin.delete_view(request, object_id, extra_context=None)[ソース]¶
モデルインスタンスの削除の確認ページに対する Django のビューです。以下のノートを参照してください。
- ModelAdmin.history_view(request, object_id, extra_context=None)[ソース]¶
与えられたモデルのインスタンスに対する修正履歴を表示するページに対する Django のビューです。
前の節で詳しく説明したフック型の ModelAdmin メソッドとは異なり、これら 5 つのメソッドは、実際には admin アプリケーションの URL ディスパッチハンドラから Django ビューとして呼び出され、モデルインスタンスの CRUD 操作を扱うページをレンダリングするように設計されています。そのため、これらのメソッドを完全にオーバーライドすると、 admin アプリケーションの動作が大きく変わってしまいます。
これらのメソッドをオーバーライドする一般的な理由の 1 つは、ビューをレンダリングするテンプレートに提供されるコンテキスト・データを補強することです。以下の例では、change ビューがオーバーライドされ、レンダリングされるテンプレートに、他の方法では利用できないマッピング・データが提供されます:
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):
# ...
pass
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context["osm_data"] = self.get_osm_info()
return super().change_view(
request,
object_id,
form_url,
extra_context=extra_context,
)
これらのビューは TemplateResponse インスタンスを返し、レンダリング前のレスポンスデータを簡単にカスタマイズできます。詳細は TemplateResponse のドキュメント を参照してください。
ModelAdmin アセットの定義¶
ビューを追加したり変更したりするために、CSS や JavaScript を追加したいことがあるかもしれません。そういうときには ModelAdmin の Media インナークラスを使用します:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ["my_styles.css"],
}
js = ["my_code.js"]
staticfiles アプリ は、すべてのアセットのパスの前に STATIC_URL (STATIC_URL が None の場合は MEDIA_URL) を付与します。 フォーム上の通常のアセット定義 と同じルールが適用されます。
jQuery¶
Django admin の JavaScript は jQuery ライブラリを使用します。
ユーザが提供するスクリプトやライブラリとの衝突を避けるため、 Django の jQuery (version 3.7.1) は django.jQuery という名前空間になっています。自分の admin JavaScript で jQuery を使いたい場合、別のコピーを入れなくても、 django.jQuery オブジェクトをチェンジリストやadd/edit ビューで使用できます。また、 django.jQuery に依存する独自の管理フォームやウィジェットは、 フォーム メディア アセットの宣言 の際に js=['admin/js/jquery.init.js', …] を指定しなければなりません。
ModelAdmin クラスはデフォルトで jQuery を要件とするので、特別なニーズがない限り jQuery をメディアリソースの ModelAdmin のリストに追加する必要はありません。たとえば、jQuery ライブラリがグローバルな名前空間を持つ必要がある場合 (たとえば、サードパーティの jQuery プラグインを使用する場合など)、もしくは jQuery の新しいバージョンを使いたい場合には、自分自身でコピーを用意する必要があります。
Django には、非圧縮と 'minified' のバージョンのjQuery があり、それぞれ jquery.js と jquery.min.js となっています。
ModelAdmin と InlineModelAdmin には、フォームやフォームセットのJavaScriptファイルへのパスを格納する Media オブジェクトのリストを返す media プロパティがあります。 DEBUG が True の場合、 jquery.js を含む様々な JavaScript ファイルの圧縮されていないバージョンを返します。そうでない場合は、 "minify" されたバージョンを返します。
カスタムのバリデーションを admin に追加する¶
また、管理画面でデータのカスタムバリデーションを追加することもできます。自動管理インターフェイスは django.forms を再利用し、 ModelAdmin クラスは独自のフォームを定義する機能を提供します:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm は必要な場所をインポートすればどこでも定義できます。これでフォームの中で任意のフィールドに対して独自のカスタムバリデーションを追加できます:
class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
ここで ModelForm を使用することは重要です。そうしないと問題が発生する可能性があります。 カスタムバリデーション に関する フォーム のドキュメント、そしてより具体的には モデルフォームのバリデーションに関する注意事項 を参照してください。
InlineModelAdmin オブジェクト¶
- class InlineModelAdmin¶
- class StackedInline[ソース]¶
admin インターフェースには、親モデルと同じページでモデルを編集する機能があります。この機能をインラインと呼びます。以下の 2 つのモデルがあるとしましょう:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=100)
author のページで、author が書いた book を編集できます。
ModelAdmin.inlines内でモデルに対するインラインを追加します:from django.contrib import admin from myapp.models import Author, Book class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [ BookInline, ] admin.site.register(Author, AuthorAdmin)
Django には、以下の通り
InlineModelAdminのサブクラスが 2 つあります:この 2 つの違いは、単にレンダリングするために使われるテンプレートの違いです。
InlineModelAdmin のオプション¶
InlineModelAdmin は ModelAdmin と多くの機能を共有しており、さらにいくつかの独自の機能を有しています (共有の機能は実際には BaseModelAdmin 基底クラスで定義されています)。共有の機能は下記です:
InlineModelAdmin クラスは、以下を追加またはカスタマイズしています:
- InlineModelAdmin.model¶
インラインが使用するモデルです。これは必須です。
- InlineModelAdmin.fk_name¶
モデルの外部キーの名前です。多くの場合、これは自動的に処理されますが、同じ親モデルに対して複数の外部キーがある場合には
fk_nameを明示的に指定する必要があります。
- InlineModelAdmin.formset¶
これはデフォルトでは
BaseInlineFormSetです。自分自身のフォームセットを使用すると、カスタマイズの幅が広がります。インラインは モデル フォームセット で構築されます。
- InlineModelAdmin.form¶
formに対する値で、デフォルトはModelFormです。これは、このインラインに対してフォームセットが生成される際にinlineformset_factory()に渡されるものです。
警告
InlineModelAdmin フォーム用のカスタムバリデーションを書く際には、親モデルの機能に依存したバリデーションを書くことに注意してください。親モデルがバリデーションに失敗した場合、 ModelForm の検証 (バリデーション) の警告に記述されているように、一貫性のない状態で放置される可能性があります。
- InlineModelAdmin.classes¶
インラインでレンダリングされるフィールドセットに適用する追加のCSSクラスを含むリストまたはタプルです。デフォルトは
Noneです。fieldsetsで設定されたクラスと同様に、collapseクラスが付けられたインラインは、展開可能なウィジェットを使用して初期状態で折りたたまれます。Changed in Django 5.1:collapseクラスを使用するfieldsetsは、nameが定義されている場合、<details>および<summary>要素を使用するようになりました。
- InlineModelAdmin.extra¶
フォームセットが初期のフォームに加えて表示する追加的なフォームの数をコントロールします。デフォルトは 3 です。詳しくは フォームセットのドキュメント を参照してください。
JavaScript が有効なブラウザを使っているユーザーに対しては、"1 つ追加" のリンクが提供され、
extra引数の結果提供されるインラインに加えていくつでもインラインを追加できます。現在表示されているフォームの数が
max_numを超えている場合、またはユーザーが JavaScript を有効にしていない場合、ダイナミックリンクは表示されません。InlineModelAdmin.get_extra()でも追加フォームの数をカスタマイズできます。
- InlineModelAdmin.max_num¶
インラインに表示するフォームの最大数をコントロールします。オブジェクトの数と直接関係はありませんが、値が小さい場合には関係する可能性があります。詳しくは 編集可能なオブジェクトの数を制限する を参照してください。
InlineModelAdmin.get_max_num()でも追加フォームの最大数をカスタマイズできます。
- InlineModelAdmin.min_num¶
インラインに表示するフォームの最小数をコントロールします。詳しくは
modelformset_factory()を参照してください。InlineModelAdmin.get_min_num()でも追加フォームの最小数をカスタマイズできます。
- InlineModelAdmin.raw_id_fields¶
デフォルトでは、
ForeignKeyのフィールドに対して Django の admin はセレクトボックスのインターフェース (<select>) を使用します。ドロップダウン内に表示する関係インスタンスをすべて選択するオーバーヘッドから逃れたいこともあるでしょう。raw_id_fieldsは、ForeignKeyやManyToManyFieldに対するInputウィジェットを適用したいフィールドのリストです:class BookInline(admin.TabularInline): model = Book raw_id_fields = ["pages"]
- InlineModelAdmin.template¶
ページ上でインラインをレンダリングするのに使われるテンプレートです。
- InlineModelAdmin.verbose_name¶
モデル内部の
Metaクラスのverbose_nameのオーバーライドです。
- InlineModelAdmin.verbose_name_plural¶
モデル内部の
Metaクラスのverbose_name_pluralをオーバーライドします。これが与えられず、InlineModelAdmin.verbose_nameが定義されている場合、 Django はInlineModelAdmin.verbose_name+'s'を使用します。
- InlineModelAdmin.can_delete¶
インライン内でインラインオブジェクトを削除可能にするかどうかを指定します。デフォルトは
Trueです。
- InlineModelAdmin.show_change_link¶
admin 内で変更可能なインラインオブジェクトをが変更フォームへのリンクを持つかどうかを指定します。デフォルトは
Falseです。
- InlineModelAdmin.get_formset(request, obj=None, **kwargs)¶
admin の追加/変更ビューで使用する
BaseInlineFormSetクラスを返します。objは編集対象の親オブジェクト、または新しい親オブジェクトを追加する場合はNoneです。ModelAdmin.get_formsets_with_inlinesの例を参照してください。
- InlineModelAdmin.get_extra(request, obj=None, **kwargs)¶
使用する追加インラインフォームの数を返します。デフォルトでは、
InlineModelAdmin.extra属性を返します。プログラムに従って追加インラインフォームの数を決めたい場合、このメソッドをオーバーライドしてください。たとえば、モデルインスタンス (キーワード引数の
objで渡されています) に基づいて数を決められます:class BinaryTreeAdmin(admin.TabularInline): model = BinaryTree def get_extra(self, request, obj=None, **kwargs): extra = 2 if obj: return extra - obj.binarytree_set.count() return extra
- InlineModelAdmin.get_max_num(request, obj=None, **kwargs)¶
使用する追加インラインフォームの最大数を返します。デフォルトでは、
InlineModelAdmin.max_num属性を返します。プログラムに従ってインラインフォームの最大数を決めたい場合、このメソッドをオーバーライドしてください。たとえば、モデルインスタンス (キーワード引数の
objで渡されています) に基づいて最大数を決められます:class BinaryTreeAdmin(admin.TabularInline): model = BinaryTree def get_max_num(self, request, obj=None, **kwargs): max_num = 10 if obj and obj.parent: return max_num - 5 return max_num
- InlineModelAdmin.get_min_num(request, obj=None, **kwargs)¶
使用する追加インラインフォームの最小数を返します。デフォルトでは、
InlineModelAdmin.min_num属性を返します。プログラムに従ってインラインフォームの最小数を決めたい場合、このメソッドをオーバーライドしてください。たとえば、モデルインスタンス (キーワード引数の
objで渡されています) に基づいて最小数を決められます:
- InlineModelAdmin.has_add_permission(request, obj)¶
インラインオブジェクトの追加が許可されている場合
Trueを、そうでなければFalseを返します。objは編集される親オブジェクトか、新規追加の場合にはNoneとなります。
- InlineModelAdmin.has_change_permission(request, obj=None)¶
インラインオブジェクトの編集が許可されている場合
Trueを、そうでなければFalseを返します。objは編集される親オブジェクトです。
- InlineModelAdmin.has_delete_permission(request, obj=None)¶
インラインオブジェクトの削除が許可されている場合
Trueを、そうでなければFalseを返します。objは編集される親オブジェクトです。
注釈
InlineModelAdmin メソッドに渡される obj 引数は編集対象の親オブジェクト、または新しい親オブジェクトを追加する場合は None です。
同じ親モデルへの複数の外部キーを持つモデルを扱う¶
同じモデルに対する複数の外部キーを持つこともあり得ます。例として以下のモデルを見てみましょう:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Friendship(models.Model):
to_person = models.ForeignKey(
Person, on_delete=models.CASCADE, related_name="friends"
)
from_person = models.ForeignKey(
Person, on_delete=models.CASCADE, related_name="from_friends"
)
Person の admin の追加や変更ページでインラインを表示したい場合は、自動的に判別することができないため、外部キーを明示的に定義する必要があります:
from django.contrib import admin
from myapp.models import Friendship, Person
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
admin.site.register(Person, PersonAdmin)
多対多のモデルを扱う¶
デフォルトでは、多対多のリレーションに対する管理ウィジェットは、実際に ManyToManyField への参照を含むモデルに表示されます。 ModelAdmin の定義に応じて、モデル内の各多対多フィールドは標準のHTML <select multiple>, 水平または垂直フィルタ、または raw_id_fields ウィジェットによって表されます。しかし、これらのウィジェットをインラインで置き換えることもできます。
次のようなモデルがあるとします:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, related_name="groups")
インラインを使用して多対多のリレーションを表示したい場合、リレーションシップに InlineModelAdmin オブジェクトを定義することで表示できます:
from django.contrib import admin
from myapp.models import Group
class MembershipInline(admin.TabularInline):
model = Group.members.through
class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ["members"]
admin.site.register(Group, GroupAdmin)
この例で注目すべき点は2つです。
まず、 MembershipInline クラスは Group.members.through を参照しています。 through 属性は多対多のリレーションを管理するモデルへの参照です。このモデルは、多対多のフィールドを定義したときに Django が自動的に作成します。
次に、 GroupAdmin は手動で members フィールドを除外する必要があります。Django は多対多のフィールドの管理ウィジェットを、リレーションを定義するモデル (この場合は Group) 上に表示します。インラインモデルを使って多対多のリレーションを表現したい場合は、 Django の admin に、このウィジェットを 表示しない ように指示しなければなりません。
このテクニックを使う場合、 m2m_changed シグナルはトリガーされないことに注意してください。これは、admin にとっては through は多対多のリレーションではなく、2つの外部キーフィールドを持つモデルに過ぎないからです。
その他の点では InlineModelAdmin は他のものと全く同じです。通常の ModelAdmin プロパティを使用して外観をカスタマイズできます。
多対多の中間モデルとともに使う¶
ManyToManyField の through 引数で中間モデルを指定した場合、管理画面はデフォルトではウィジェットを表示しません。これは、その中間モデルの各インスタンスは、単一のウィジェットで表示できる以上の情報を必要とし、複数のウィジェットに必要なレイアウトは中間モデルによって異なるからです。
しかし、インラインで情報を編集できるようにしたいと思うでしょう。幸いなことに、インライン admin モデルでこれを実現できます。次のようなモデルがあるとします:
from django.db import models
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, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "group"], name="unique_person_group"
)
]
この中間モデルを管理画面に表示するための最初のステップは Membership モデルのインラインクラスを定義することです:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
この例では Membership モデルにデフォルトの InlineModelAdmin の値を使用し、追加の追加フォームを 1 つに制限しています。これは InlineModelAdmin クラスで利用可能なオプションを使ってカスタマイズできます。
次に Person と Group モデルの管理ビューを作成します:
class PersonAdmin(admin.ModelAdmin):
inlines = [MembershipInline]
class GroupAdmin(admin.ModelAdmin):
inlines = [MembershipInline]
最後に、 Person と Group のモデルを管理サイトに登録します:
admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)
これであなたの管理サイトは Person または Group の詳細ページから Membership オブジェクトをインラインで編集できるように設定されました。
ジェネリックリレーションをインラインとして使う¶
ジェネリックリレーションを定義されたオブジェクトでインラインを使用することもできます。以下のようなモデルがあるとします:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Product の追加/変更ビューで Image インスタンスの編集や作成を可能にしたい場合、 admin によって提供される GenericTabularInline や GenericStackedInline (どちらも GenericInlineModelAdmin のサブクラス)を使用できます。これらはそれぞれ、インラインオブジェクトを表すフォームのための tabular 形式と stack 形式のビジュアルレイアウトを実装しており、ジェネリックでないものと同様です。これらは他のインラインと全く同じように動作します。この例のアプリのための admin.py では次のようにします:
from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from myapp.models import Image, Product
class ImageInline(GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
詳しくは contenttypes のドキュメント を参照してください。
admin テンプレートをオーバーライドする¶
admin モジュールが admin サイトの様々なページを生成するために使用するテンプレートの多くはオーバーライドできます。特定のアプリや特定のモデルのためにこれらのテンプレートの一部をオーバーライドすることもできます。
プロジェクトの admin テンプレートディレクトリを設定する¶
admin テンプレートファイルは django/contrib/admin/templates/admin ディレクトリにあります。
そのうちの一つ以上を上書きするには、まずプロジェクトの templates ディレクトリに admin ディレクトリを作成してください。これは DjangoTemplates バックエンドの DIRS オプションの TEMPLATES 設定で指定したディレクトリのどれでもかまいません。 'loaders' オプションをカスタマイズしている場合は、 'django.template.loaders.app_directories.Loader' の前に 'django.template.loaders.filesystem.Loader' が表示されていることを確認してください。そうすれば、 django.contrib.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_form.html を見ると、 object-tools-items ブロックをオーバーライドするだけでよいことがわかります。そこで、以下に新しい change_form.html の例を示します:
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
<li>
<a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
</li>
<li>
<a href="mylink/" class="historylink">My Link</a>
</li>
{% if has_absolute_url %}
<li>
<a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
</li>
{% endif %}
{% endblock %}
これで完了です!このファイルを templates/admin/my_app ディレクトリに置くと、my_app 内のすべてのモデルの変更フォームにリンクが表示されます。
アプリやモデルごとにオーバーライド可能なテンプレート¶
contrib/admin/templates/admin にある全てのテンプレートがアプリやモデルごとにオーバーライドできるわけではありません。以下のものは可能です:
actions.htmlapp_index.htmlchange_form.htmlchange_form_object_tools.htmlchange_list.htmlchange_list_object_tools.htmlchange_list_results.htmldate_hierarchy.htmldelete_confirmation.htmlobject_history.htmlpagination.htmlpopup_response.htmlprepopulated_fields_js.htmlsearch_form.htmlsubmit_line.html
この方法でオーバーライドできないテンプレートについては、 templates/admin ディレクトリに新しいバージョンを置くことで、プロジェクト全体でオーバーライドできます。これは特に独自の404ページや500ページを作成するのに便利です。
注釈
change_list_results.html のようないくつかの管理用テンプレートはカスタムインクルージョンタグのレンダリングに使用されます。これらはオーバーライドできますが、そのような場合、おそらく問題のタグの独自のバージョンを作成し、別の名前を付けた方が良いでしょう。そうすれば、選択的に使用できます。
ルートテンプレートとログインテンプレート¶
インデックス、ログイン、ログアウトのテンプレートを変更したい場合は、独自の AdminSite インスタンス(下記参照)を作成し、 AdminSite.index_template 、 AdminSite.login_template 、 AdminSite.logout_template プロパティを変更した方が良いでしょう。
テーマのサポート¶
管理画面では、CSS 変数を使用して色とフォントを定義します。これにより、多くの個別の CSS ルールを上書きすることなくテーマを変更できます。たとえば、青の代わりに紫を使うには、以下のような admin/base.html テンプレートをプロジェクトに追加します。
{% extends 'admin/base.html' %}
{% block extrastyle %}{{ block.super }}
<style>
html[data-theme="light"], :root {
--primary: #9774d5;
--secondary: #785cab;
--link-fg: #7c449b;
--link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}
CSS 変数のリストは django/contrib/admin/static/admin/css/base.css で定義されています。
prefers-color-scheme メディアクエリを尊重したダークモード変数は django/contrib/admin/static/admin/css/dark_mode.css で定義されています。これは {% block dark-mode-vars %} のドキュメントにリンクされています。
extrabody ブロック¶
カスタムの HTML や JavaScript 、その他のコンテンツを、admin/base.html を継承するテンプレートの閉じる </body> タグの直前に表示させたい場合は、 extrabody ブロックを拡張することで実現できます。たとえば、ページ読み込み時にアラートを表示させたい場合、プロジェクトに admin/base.html のテンプレートオーバーライドを追加することで対応できます。
{% extends 'admin/base.html' %}
{% block extrabody %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
window.alert('Welcome!');
});
</script>
{% endblock extrabody %}
AdminSite オブジェクト¶
- class AdminSite(name='admin')[ソース]¶
Django の admin サイトは
django.contrib.admin.sites.AdminSiteのインスタンスで表現されます。デフォルトでは、このクラスのインスタンスはdjango.contrib.admin.siteとして作成され、モデルやModelAdminインスタンスを登録できます。デフォルトのadminサイトをカスタマイズしたい場合は、 オーバーライド することができます。
管理サイト
AdminSiteのインスタンスを作成する際には、コンストラクタのname引数に一意なインスタンス名を指定できます。このインスタンス名はインスタンスを識別するために使用され、特に 管理用URL を逆引きするときに使用されます。インスタンス名を指定しなかった場合、デフォルトのインスタンス名adminが使用されます。AdminSiteクラスをカスタマイズする例については AdminSite クラスのカスタマイズ を参照してください。
AdminSite の属性¶
テンプレートは admin テンプレートをオーバーライドする で説明されているように、基本管理テンプレートを上書きしたり拡張したりすることができます。
- AdminSite.site_header¶
各管理ページの上部に表示するテキストを
<div>(文字列) で指定します。デフォルトでは "Django administration" です。
- AdminSite.site_title¶
各管理ページの
<title>の末尾に付けるテキスト (文字列)。デフォルトでは "Django site admin" です。
- AdminSite.site_url¶
各管理ページの上部にある "サイトを見る "リンクのURL。デフォルトでは
site_urlは/です。リンクを削除するにはNoneを指定してください。サブパス上で動作しているサイトでは、
each_context()メソッドは現在のリクエストにrequest.META['SCRIPT_NAME']が設定されているかどうかをチェックし、site_urlに/以外の値が設定されていなければ、その値を使用します。
- AdminSite.index_title¶
管理インデックスページのトップに表示するテキスト(文字列)。デフォルトでは "Site administration "です。
- AdminSite.index_template¶
admin サイトのメインインデックスビューで使用されるカスタムテンプレートへのパス。
- AdminSite.app_index_template¶
admin サイトのアプリ インデックスビューで使用されるカスタムテンプレートへのパス。
- AdminSite.empty_value_display¶
admin サイトのチェンジリストで空の値を表示する際に使用する文字列。デフォルトはダッシュです。この値はフィールドに
empty_value_display属性を指定することで、ModelAdminごとやModelAdmin内のカスタムフィールドごとにオーバーライドできます。例についてはModelAdmin.empty_value_displayを参照してください。
大きな画面でナビゲーションサイドバーを表示するかどうかを決定する真偽値。デフォルトでは
Trueに設定されています。
- AdminSite.final_catch_all_view¶
認証されていないユーザーをログインページにリダイレクトさせる最終キャッチオールビューを管理画面に追加するかどうかを決定する真偽値。デフォルトでは
Trueに設定されています。警告
このビューはモデル列挙のプライバシーに関する潜在的な問題から保護するため、これを
Falseに設定することは推奨されません。
- AdminSite.login_template¶
admin サイトのログインビューで使用されるカスタムテンプレートへのパス。
- AdminSite.login_form¶
admin サイトのログインビューで使用される
AuthenticationFormのサブクラス。
- AdminSite.logout_template¶
admin サイトのログアウトビューで使用されるカスタムテンプレートへのパス。
- AdminSite.password_change_template¶
admin サイトのパスワード変更ビューで使用されるカスタムテンプレートへのパス。
- AdminSite.password_change_done_template¶
adminサイトのパスワード変更完了ビューで使用されるカスタムテンプレートへのパス。
AdminSite のメソッド¶
- AdminSite.each_context(request)[ソース]¶
admin サイトの各ページのテンプレートコンテキストに置く変数の辞書を返します。
デフォルトで以下の変数と値が含まれています:
site_header:AdminSite.site_headersite_title:AdminSite.site_titlesite_url:AdminSite.site_urlhas_permission:AdminSite.has_permission()available_apps: アプリケーションレジストリ から現在のユーザーが利用できるアプリケーションのリストです。リストの各エントリは以下のキーを持つアプリケーションを表す dict です:app_label: アプリケーションのラベルapp_url: admin のアプリケーションインデックスの URLhas_module_perms: 現在のユーザーに対して、モジュールのインデックスページの表示とアクセスが許可されているかどうかを示す真偽値。models: アプリケーションで利用可能なモデルのリスト。
各 model は以下のキーを持つ dict です:
model: モデルクラスobject_name: モデルのクラス名name: 複数形のモデル名perms:add,change,delete,viewのパーミッションをトラッキングするdict。admin_url: モデルの管理用チェンジリストのURLadd_url: 新しいモデルインスタンスを追加するための管理用URL
is_popup: 現在のページがポップアップウィンドウで表示されるかどうかis_nav_sidebar_enabled:AdminSite.enable_nav_sidebarlog_entries:AdminSite.get_log_entries()
- AdminSite.get_app_list(request, app_label=None)[ソース]¶
アプリケーションレジストリ から、現在のユーザーが利用できるアプリケーションのリストを返します。オプションで
app_label引数を渡すことで、単一のアプリケーションの詳細を取得できます。リストの各エントリは以下のキーを持つアプリケーションを表す辞書です:app_label: アプリケーションのラベルapp_url: admin のアプリケーションインデックスの URLhas_module_perms: 現在のユーザーに対して、モジュールのインデックスページの表示とアクセスが許可されているかどうかを示す真偽値。models: アプリケーションで利用可能なモデルのリスト。name: アプリケーションの名前
各 model は以下のキーを持つ辞書です:
model: モデルクラスobject_name: モデルのクラス名name: 複数形のモデル名perms:add,change,delete,viewのパーミッションをトラッキングするdict。admin_url: モデルの管理用チェンジリストのURLadd_url: 新しいモデルインスタンスを追加するための管理用URL
アプリケーションとモデルのリストはそれらの名前によってアルファベット順にソートされます。このメソッドをオーバーライドして、管理インデックスページのデフォルトの並び順を変更できます。
- AdminSite.has_permission(request)[ソース]¶
指定された
HttpRequestのユーザが admin サイトの少なくとも1つのページを閲覧する権限を持っている場合にTrueを返します。デフォルトはUser.is_activeとUser.is_staffの両方がTrueである必要があります。
- AdminSite.register(model_or_iterable, admin_class=None, **options)[ソース]¶
指定された model クラス (またはクラスのイテラブル) を指定された
admin_classとともに登録します。admin_classはデフォルトでModelAdmin(デフォルトの管理オプション) になります。キーワード引数 (たとえばlist_display) が与えられた場合、それらは admin クラスのオプションとして適用されます。モデルが抽象クラスの場合は
ImproperlyConfiguredを、モデルが既に登録されている場合はdjango.contrib.admin.exceptions.AlreadyRegisteredを発生させます。
- AdminSite.unregister(model_or_iterable)[ソース]¶
指定されたモデルクラス(またはクラスのイテラブル)の登録を解除します。
モデルが登録されていない場合、
django.contrib.admin.exceptions.NotRegisteredを発生させます。
URLconf に AdminSite インスタンスをフックします。¶
Django admin のセットアップの最後のステップは、 AdminSite インスタンスを URLconf にフックすることです。指定した URL を AdminSite.urls メソッドで指定します。 include() を使う必要はありません。
このインスタンスでは、デフォルトの AdminSite インスタンス django.contrib.admin.site を URL /admin/ に登録します:
# urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path("admin/", admin.site.urls),
]
AdminSite クラスのカスタマイズ¶
カスタムの動作で独自の admin サイトを設定したい場合は、自由に AdminSite をサブクラス化し、好きなものをオーバーライドしたり追加したりすることができます。そして、 AdminSite サブクラスのインスタンスを作成し (他の Python クラスと同じようにインスタンスを作成します)、モデルや ModelAdmin サブクラスをデフォルトのサイトではなく、サブクラスに登録します。最後に、 myproject/urls.py を更新して、 AdminSite サブクラスを参照するようにします。
myapp/admin.py¶from django.contrib import admin
from .models import MyModel
class MyAdminSite(admin.AdminSite):
site_header = "Monty Python administration"
admin_site = MyAdminSite(name="myadmin")
admin_site.register(MyModel)
myproject/urls.py¶from django.urls import path
from myapp.admin import admin_site
urlpatterns = [
path("myadmin/", admin_site.urls),
]
自分の AdminSite インスタンスを使う場合、アプリごとの admin モジュールを全て myproject.admin モジュールにインポートする可能性が高いので、 admin モジュールを自動検出させたくないかも知れないことに注意してください。つまり、 INSTALLED_APPS 設定に 'django.contrib.admin' の代わりに 'django.contrib.admin.apps.SimpleAdminConfig' を記述する必要があります。
デフォルトの admin サイトをオーバーライドする¶
デフォルトの django.contrib.admin.site をオーバーライドするには、カスタム AppConfig の default_site 属性に AdminSite サブクラスまたはサイトのインスタンスを返す呼び出し可能オブジェクトのドット区切りインポートパスを指定します。
myproject/admin.py¶from django.contrib import admin
class MyAdminSite(admin.AdminSite): ...
myproject/apps.py¶from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = "myproject.admin.MyAdminSite"
myproject/settings.py¶INSTALLED_APPS = [
# ...
"myproject.apps.MyAdminConfig", # replaces 'django.contrib.admin'
# ...
]
同じ URLconf に複数の admin サイトを置く¶
同じ Django を使った Web サイトに、複数の admin サイトのインスタンスを作成できます。 AdminSite のインスタンスを複数作成し、それぞれを異なる URL に配置します。
このインスタンスでは、 /basic-admin/ と /advanced-admin/ はそれぞれ AdminSite インスタンス myproject.admin.basic_site と myproject.admin.advanced_site を使用した別々のバージョンの admin サイトです:
# urls.py
from django.urls import path
from myproject.admin import advanced_site, basic_site
urlpatterns = [
path("basic-admin/", basic_site.urls),
path("advanced-admin/", advanced_site.urls),
]
AdminSite インスタンスはコンストラクタに一つの引数、名前を渡します。この引数は 逆引き のためにURL名のプレフィックスとなります。これは複数の AdminSite を使用する場合にのみ必要です。
admin サイトにビューを追加する¶
ModelAdmin と同様に、 AdminSite は get_urls() メソッドを提供し、このメソッドをオーバーライドすることでサイトに追加のビューを定義できます。admin サイトに新しいビューを追加するには、ベースとなる get_urls() メソッドを拡張して、新しいビューのパターンを追加します。
注釈
admin テンプレートを使用する、またはベースとなる admin テンプレートを拡張するビューは、テンプレートをレンダリングする前に request.current_app を設定する必要があります。ビューが AdminSite にある場合は self.name を、ビューが ModelAdmin にある場合は self.admin_site.name を設定します。
パスワードリセット機能を追加する¶
URLconfに数行を追加することで、admin サイトにパスワードリセット機能を追加できます。具体的には、以下の4つのパターンを追加します:
from django.contrib import admin
from django.contrib.auth import views as auth_views
path(
"admin/password_reset/",
auth_views.PasswordResetView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="admin_password_reset",
),
path(
"admin/password_reset/done/",
auth_views.PasswordResetDoneView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_done",
),
path(
"reset/<uidb64>/<token>/",
auth_views.PasswordResetConfirmView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_confirm",
),
path(
"reset/done/",
auth_views.PasswordResetCompleteView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_complete",
),
(上記は admin/ に admin を追加していることを前提としており、admin アプリ自体を含む行の前に ^admin/ で始まるURLを配置することが必要です)
admin_password_reset という名前のURLがあると、デフォルトの admin ログインページのパスワードボックスの下に "forgot your password? "というリンクが表示されます。
LogEntry オブジェクト¶
- class models.LogEntry¶
LogEntryクラスは管理画面を通して行われたオブジェクトの追加、変更、削除を記録します。
LogEntry の属性¶
- LogEntry.action_time¶
アクションの日時。
- LogEntry.user¶
アクションを実行したユーザー(
AUTH_USER_MODELインスタンス)。
- LogEntry.content_type¶
変更されたオブジェクトの
ContentType。
- LogEntry.object_id¶
変更されたオブジェクトの主キーのテキスト表現。
- LogEntry.object_repr¶
変更後のオブジェクトの
repr()。
- LogEntry.action_flag¶
ログに記録されたアクションの種類:
ADDITION,CHANGE,DELETION。たとえば、admin を通して行われたすべての追加操作のリストを取得する場合:
from django.contrib.admin.models import ADDITION, LogEntry LogEntry.objects.filter(action_flag=ADDITION)
- LogEntry.change_message¶
変更の詳細。たとえば編集の場合、メッセージには編集されたフィールドのリストが含まれます。Django の admin サイトでは、この内容を JSON 構造として整形し、
get_change_message()が現在のユーザ言語で翻訳されたメッセージを再構成できるようにしています。カスタムコードではこれをプレーンな文字列として設定するかもしれません。この値を取得するには、直接アクセスするのではなくget_change_message()メソッドを使用することをお勧めします。
LogEntry メソッド¶
- LogEntry.get_change_message()[ソース]¶
change_messageを現在のユーザ言語に変換します。Django 1.10 より前に作成されたメッセージは、常にログに記録された言語で表示されます。
admin の URL を逆引きする¶
AdminSite がデプロイされると、そのサイトが提供するビューは Django の URL 逆引きシステム を使ってアクセスできるようになります。
AdminSite は以下のURLパターンを提供します:
ページ |
URL 名 |
パラメータ |
|---|---|---|
インデックス |
|
|
ログイン |
|
|
ログアウト |
|
|
パスワードの変更 |
|
|
パスワード変更完了 |
|
|
国際化 JavaScript |
|
|
アプリケーションのインデックスページ |
|
|
オブジェクトのページへのリダイレクト |
|
|
それぞれの ModelAdmin インスタンスは追加の名前付き URL のセットを提供します:
ページ |
URL 名 |
パラメータ |
|---|---|---|
チェンジリスト |
|
|
追加 |
|
|
履歴 |
|
|
削除 |
|
|
変更 |
|
|
UserAdmin は以下の名前付きURLを提供します:
ページ |
URL 名 |
パラメータ |
|---|---|---|
パスワードの変更 |
|
|
これらの名前付きURLはアプリケーション名前空間 admin とサイトインスタンス名に対応するインスタンス名前空間に登録されます。
つまり、デフォルトの admin 画面で特定の Choice オブジェクト(投票アプリケーションから)の変更ビューへの参照を取得したい場合、次のように呼び出します:
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,))
これは、最初に登録された管理アプリケーションのインスタンスを(インスタンス名が何であっても)見つけ、そのインスタンスで poll.Choice インスタンスを変更するためのビューを解決します。
特定の管理インスタンスのURLを見つけたい場合は、そのインスタンス名を current_app ヒントとして逆引きのコールに与えます。たとえば、特に custom という名前の管理インスタンスから管理ビューを取得したい場合は、以下のように呼び出す必要があります。
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")
詳細は 名前空間のURLの逆引き のドキュメントを参照してください。
Django は、テンプレート内で admin の URL を簡単に逆引きできるように、アクション を引数に取る admin_urlname フィルタを提供しています:
{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>
上記の例のアクションは上記の ModelAdmin インスタンスの URL 名の最後の部分と一致します。変数 opts には app_label と model_name 属性を持つ任意のオブジェクトを指定することができ、通常は現在のモデルの管理ビューから提供されます。
display デコレータ¶
- display(*, boolean=None, ordering=None, description=None, empty_value=None)[ソース]¶
このデコレータは
list_displayやreadonly_fieldsで使用できるカスタム表示関数に特定の属性を指定するために使用できます:@admin.display( boolean=True, ordering="-publish_date", description="Is Published?", ) def is_published(self, obj): return obj.publish_date is not None
これは、いくつかの属性を(元の長い名前で)関数に直接設定することと等価です。
def is_published(self, obj): return obj.publish_date is not None is_published.boolean = True is_published.admin_order_field = "-publish_date" is_published.short_description = "Is Published?"
また、
empty_valueデコレータパラメータは、関数に直接割り当てられたempty_value_display属性にマッピングされることに注意してください。真偽値booleanと併用することはできません。このデコレータの使用は、表示関数を作成する上で必須ではありませんが、 関数の目的を特定するための目印として、引数なしで使用すると便利です:
@admin.display def published_year(self, obj): return obj.publish_date.year
この場合、関数に属性は追加されません。
staff_member_required デコレータ¶
- staff_member_required(redirect_field_name='next', login_url='admin:login')[ソース]¶
このデコレータは、認可が必要な admin ビューで使用されます。この関数でデコレーションされたビューは、以下の動作をするようになります。
ユーザーがログインしており、スタッフであり(
User.is_staff=True)、アクティブであれば(User.is_active=True)、ビューを正常に実行します。そうでない場合、リクエストは
login_urlパラメータで指定された URL にリダイレクトされ、redirect_field_nameで指定されたクエリ文字列変数に元々リクエストされていたパスが格納されます。例:/admin/login/?next=/admin/polls/question/3/。
使用例:
from django.contrib.admin.views.decorators import staff_member_required @staff_member_required def my_view(request): ...