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
以外の各フィールドを、単一のフィールドセットで、モデル内でフィールドが定義されたとおりの順番で表示します。
- 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)
Changed in Django 5.0:プロパティの
boolean
属性をサポートしました。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¶
- New in Django 5.0.
管理画面のチェンジリストのフィルタにファセット数を表示するかどうかを制御します。デフォルトは
ShowFacets.ALLOW
です。表示されている場合、ファセット数は現在適用されているフィルタに合わせて更新されます。
- class ShowFacets¶
- New in Django 5.0.
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_fields
Input
ウィジェットには、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
インスタンスを使ってCar
ForeignKey フィールドをフィルタし、特定の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
サブクラスで許可されるルックアップをカスタマイズするには、このメソッドをオーバーライドします。Changed in Django 5.0:request
引数が追加されました。
- 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', …]
を指定しなければなりません。
jQueryが 3.6.4 から 3.7.1 にアップグレードされました。
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 class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [ BookInline, ]
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 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
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
多対多のモデルを扱う¶
デフォルトでは、多対多のリレーションに対する管理ウィジェットは、実際に 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
class MembershipInline(admin.TabularInline):
model = Group.members.through
class PersonAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ["members"]
この例で注目すべき点は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)
この中間モデルを管理画面に表示するための最初のステップは 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.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.html
app_index.html
change_form.html
change_form_object_tools.html
change_list.html
change_list_object_tools.html
change_list_results.html
date_hierarchy.html
delete_confirmation.html
object_history.html
pagination.html
popup_response.html
prepopulated_fields_js.html
search_form.html
submit_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 %}
のドキュメントにリンクされています。
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" です。Changed in Django 5.0:古いバージョンでは
site_header
は<h1>
タグを使用していました。
- 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_header
site_title
:AdminSite.site_title
site_url
:AdminSite.site_url
has_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_sidebar
log_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
サブクラスを参照するようにします。
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)
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
サブクラスまたはサイトのインスタンスを返す呼び出し可能オブジェクトのドット区切りインポートパスを指定します。
from django.contrib import admin
class MyAdminSite(admin.AdminSite): ...
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = "myproject.admin.MyAdminSite"
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): ...