Django 管理網站¶
Django 最強大的部分之一是自動管理介面。它會從您的模型讀取元數據,以提供一個快速、以模型為中心的介面,讓受信任的使用者可以管理您網站上的內容。管理介面建議的使用方式僅限於組織的內部管理工具。它不適用於建立您整個前端介面。
管理介面有很多客製化的掛鉤,但請注意不要只嘗試使用這些掛鉤。如果您需要提供一個更以流程為中心的介面,以抽象化資料庫表格和欄位的實作細節,那麼這可能是時候編寫您自己的視圖了。
在本文件中,我們將討論如何啟用、使用和客製化 Django 的管理介面。
總覽¶
管理介面在 startproject
使用的預設專案範本中啟用。
如果您沒有使用預設專案範本,以下是需求
將
'django.contrib.admin'
及其相依性 -django.contrib.auth
、django.contrib.contenttypes
、django.contrib.messages
和django.contrib.sessions
- 新增到您的INSTALLED_APPS
設定。在您的
TEMPLATES
設定中,使用django.template.context_processors.request
、django.contrib.auth.context_processors.auth
和django.contrib.messages.context_processors.messages
在OPTIONS
的'context_processors'
選項中設定DjangoTemplates
後端。如果您已客製化
MIDDLEWARE
設定,則必須包含django.contrib.sessions.middleware.SessionMiddleware
、django.contrib.auth.middleware.AuthenticationMiddleware
和django.contrib.messages.middleware.MessageMiddleware
。
完成這些步驟後,您將可以透過瀏覽您連結的 URL 來使用管理網站(預設為 /admin/
)。
如果您需要建立一個使用者來登入,請使用 createsuperuser
命令。預設情況下,登入管理介面需要使用者將 is_staff
屬性設定為 True
。
最後,判斷您的應用程式的哪些模型應該在管理介面中可編輯。對於每個模型,請依照 ModelAdmin
中的說明,將其註冊到管理介面。
其他主題¶
ModelAdmin
物件¶
- class ModelAdmin[原始碼]¶
ModelAdmin
類別是模型在管理介面中的表示。通常,這些會儲存在您的應用程式中的名為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
類別尚未定義任何自訂值(尚未)。因此,將提供預設的管理介面。如果您對預設的管理介面感到滿意,則根本不需要定義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
它會獲得一個或多個模型類別,以註冊到
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
如果必須在其
__init__()
方法中參考您的模型管理類別,則無法使用此裝飾器,例如super(PersonAdmin, self).__init__(*args, **kwargs)
。您可以使用super().__init__(*args, **kwargs)
。
探索管理檔案¶
當您在 INSTALLED_APPS
設定中放入 'django.contrib.admin'
時,Django 會自動在每個應用程式中尋找 admin
模組並匯入它。
- class apps.AdminConfig¶
這是管理介面的預設
AppConfig
類別。它會在 Django 啟動時呼叫autodiscover()
。
- class apps.SimpleAdminConfig¶
此類別的作用類似於
AdminConfig
,不同之處在於它不會呼叫autodiscover()
。
- autodiscover() [原始碼]¶
此函式會嘗試在每個已安裝的應用程式中匯入一個
admin
模組。此類模組應將模型註冊到管理介面。通常您不需要直接呼叫此函式,因為
AdminConfig
會在 Django 啟動時呼叫它。
如果您正在使用自訂的 AdminSite
,通常會將所有 ModelAdmin
子類別匯入到您的程式碼中,並將它們註冊到自訂的 AdminSite
。在這種情況下,為了停用自動探索,您應該在 INSTALLED_APPS
設定中放入 'django.contrib.admin.apps.SimpleAdminConfig'
而不是 'django.contrib.admin'
。
ModelAdmin
選項¶
ModelAdmin
非常彈性。它有幾個選項可以處理自訂介面。所有選項都在 ModelAdmin
子類別中定義。
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = "pub_date"
- ModelAdmin.actions_on_top¶
- ModelAdmin.actions_on_bottom¶
控制動作列在頁面上出現的位置。預設情況下,管理變更清單會在頁面頂部顯示動作 (
actions_on_top = True; actions_on_bottom = False
)。
- ModelAdmin.actions_selection_counter¶
控制是否在動作下拉選單旁邊顯示選擇計數器。預設情況下,管理變更清單會顯示它 (
actions_selection_counter = True
)。
- ModelAdmin.date_hierarchy¶
將
date_hierarchy
設定為模型中DateField
或DateTimeField
的名稱,變更清單頁面將包含該欄位的基於日期的向下鑽研導覽。範例
date_hierarchy = "pub_date"
您也可以使用
__
查詢指定相關模型上的欄位,例如date_hierarchy = "author__pub_date"
這將根據可用的資料智能地填充自身,例如,如果所有日期都在一個月中,它將僅顯示天級的向下鑽研。
注意
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
覆寫所有管理頁面的empty_value_display
,或像這樣覆寫特定欄位的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
欄位,您應該像這樣指定fields
或exclude
from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): fields = ["name", "title"] class AuthorAdmin(admin.ModelAdmin): exclude = ["birth_date"]
由於 Author 模型只有三個欄位,
name
、title
和birth_date
,因此上述宣告產生的表單將包含完全相同的欄位。
- ModelAdmin.fields¶
使用
fields
選項,在「新增」和「變更」頁面上的表單中進行簡單的版面配置變更,例如僅顯示可用欄位的子集、修改其順序或將它們分組為多行。例如,您可以為django.contrib.flatpages.models.FlatPage
模型定義一個更簡單的管理表單,如下所示class FlatPageAdmin(admin.ModelAdmin): fields = ["url", "title", "content"]
在上面的範例中,表單中只會依序顯示
url
、title
和content
欄位。fields
可以包含在ModelAdmin.readonly_fields
中定義的值,以只讀方式顯示。對於更複雜的版面配置需求,請參閱
fieldsets
選項。fields
選項接受與list_display
相同的數值類型,但不會接受可呼叫對象和相關欄位的__
查詢。模型和模型管理方法名稱只有在它們列在readonly_fields
中時才會使用。若要在同一行顯示多個欄位,請將這些欄位包裝在自己的元組中。在此範例中,
url
和title
欄位將顯示在同一行,而content
欄位將在其自己的行中顯示在下方class FlatPageAdmin(admin.ModelAdmin): fields = [("url", "title"), "content"]
可能與
ModelAdmin.fieldsets
選項混淆這個
fields
選項不應與fieldsets
選項中的fields
字典鍵混淆,如下一節所述。如果沒有
fields
或fieldsets
選項,Django 將預設為以與模型中定義欄位相同的順序,在單個欄位集中顯示每個不是AutoField
且具有editable=True
的欄位。
- ModelAdmin.fieldsets¶
設定
fieldsets
以控制管理「新增」和「變更」頁面的版面配置。fieldsets
是一個 2 元組的列表,其中每個 2 元組代表管理表單頁面上的<fieldset>
。(<fieldset>
是表單的一個「區段」。)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"], }, ), ]
這會產生一個如下所示的管理頁面
如果既沒有
fieldsets
選項,也沒有fields
選項,Django 會預設顯示每個不是AutoField
且具有editable=True
的欄位,並將它們放在一個單一的 fieldset 中,順序與欄位在模型中定義的順序相同。field_options
字典可以有以下鍵fields
要在此 fieldset 中顯示的欄位名稱列表或元組。此鍵是必需的。
範例
{ "fields": ["first_name", "last_name", "address", "city", "state"], }
與
fields
選項一樣,若要將多個欄位顯示在同一行,請將這些欄位包裝在它們自己的元組中。在此範例中,first_name
和last_name
欄位將顯示在同一行上{ "fields": [("first_name", "last_name"), "address", "city", "state"], }
fields
可以包含在readonly_fields
中定義的值,以顯示為唯讀。如果您將可呼叫物件的名稱加入到
fields
中,則與fields
選項的規則相同:該可呼叫物件必須列在readonly_fields
中。
classes
包含要應用於 fieldset 的額外 CSS 類別的列表或元組。這可以包括專案中定義的任何自訂 CSS 類別,以及 Django 提供的任何 CSS 類別。在預設的管理站台 CSS 樣式表中,定義了兩個特別有用的類別:
collapse
和wide
。範例
{ "classes": ["wide", "collapse"], }
具有
wide
樣式的 Fieldset 在管理介面中將獲得額外的水平空間。具有名稱和collapse
樣式的 Fieldset 將會初始折疊,並使用可展開的 widget,其中包含一個切換開關以切換它們的可見性。在 Django 5.1 中變更。現在,使用
collapse
類別的fieldsets
會使用<details>
和<summary>
元素,前提是它們定義了name
。
description
一個可選的額外文字字串,將顯示在每個 fieldset 的頂部,位於 fieldset 的標題下方。
請注意,此值在管理介面中顯示時,不會進行 HTML 逸出。這讓您可以視需要包含 HTML。或者,您可以使用純文字和
django.utils.html.escape()
來逸出任何 HTML 特殊字元。
TabularInline
對fieldsets
的支援有限將
fieldsets
與TabularInline
搭配使用,功能有限。您可以透過在field_options
字典中定義fields
,指定將在TabularInline
版面配置中顯示的欄位及其順序。不支援所有其他功能。這包括使用
name
來定義欄位群組的標題。
- ModelAdmin.filter_horizontal¶
預設情況下,
ManyToManyField
在管理站台中會以<select multiple>
顯示。但是,當選取多個項目時,多選取方塊可能難以使用。將ManyToManyField
新增到此清單,將會改為使用一個精巧且不引人注意的 JavaScript「篩選」介面,允許在選項中搜尋。未選取和選取的選項會並排顯示在兩個方塊中。請參閱filter_vertical
以使用垂直介面。
- ModelAdmin.filter_vertical¶
與
filter_horizontal
相同,但是使用篩選介面的垂直顯示,其中未選取選項的方塊顯示在選取選項的方塊上方。
- ModelAdmin.form¶
預設情況下,會為您的模型動態建立
ModelForm
。它用於建立在新增/變更頁面上呈現的表單。您可以輕鬆提供自己的ModelForm
,以覆寫新增/變更頁面上的任何預設表單行為。或者,您可以使用ModelAdmin.get_form()
方法來自訂預設表單,而不是指定全新的表單。如需範例,請參閱 在管理介面中新增自訂驗證 一節。
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¶
這提供了一種快速且方便的方法,可以覆寫用於管理介面的一些
Field
選項。formfield_overrides
是一個字典,將欄位類別對應到在建構時要傳遞給欄位的參數字典。因為這有點抽象,所以讓我們看一個具體的例子。
formfield_overrides
最常見的用途是為特定類型的欄位新增自訂 widget。因此,假設我們編寫了一個RichTextEditorWidget
,我們希望將其用於大型文字欄位,而不是預設的<textarea>
。以下是我們的做法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
) 使用自訂 widget,請確保您未將該欄位的名稱包含在raw_id_fields
、radio_fields
或autocomplete_fields
中。formfield_overrides
不會讓您變更已設定raw_id_fields
、radio_fields
或autocomplete_fields
的關聯欄位上的 widget。這是因為raw_id_fields
、radio_fields
和autocomplete_fields
本身就隱含著自訂 widget。
- ModelAdmin.inlines¶
請參閱下方的
InlineModelAdmin
物件,以及ModelAdmin.get_formsets_with_inlines()
。
- ModelAdmin.list_display¶
設定
list_display
以控制管理介面的變更列表頁面上顯示哪些欄位。範例
list_display = ["first_name", "last_name"]
如果您沒有設定
list_display
,管理介面將會顯示單一欄位,該欄位會顯示每個物件的__str__()
表示法。在
list_display
中可以使用五種值類型。除了最簡單的以外,其他都可以使用display()
裝飾器,該裝飾器用於自訂欄位的呈現方式。模型欄位的名稱。例如:
class PersonAdmin(admin.ModelAdmin): list_display = ["first_name", "last_name"]
相關欄位的名稱,使用
__
標記法。例如:class PersonAdmin(admin.ModelAdmin): list_display = ["city__name"]
一個接受一個引數(即模型實例)的可呼叫物件。例如:
@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]
一個字串,表示接受一個引數(即模型實例)的
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"]
在 Django 5.1 中變更。當目標為相關欄位時,新增了對使用
__
查找的支援。關於
list_display
的一些特殊注意事項:如果欄位是
ForeignKey
,Django 將會顯示相關物件的__str__()
。不支援
ManyToManyField
欄位,因為這將需要在表格中的每一列執行單獨的 SQL 語句。如果無論如何您都想這樣做,請為您的模型提供一個自訂方法,並將該方法的名稱新增到list_display
中。(請參閱下文關於list_display
中自訂方法的更多資訊。)如果欄位是
BooleanField
,Django 將會顯示漂亮的「是」、「否」或「未知」圖示,而不是True
、False
或None
。如果給定的字串是模型、
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
、空字串或沒有元素的迭代器,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
的可呼叫物件,如果您使用display()
裝飾器包裝該方法,並傳遞boolean
引數且值設為True
,Django 將會顯示漂亮的「是」、「否」或「未知」圖示。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
中與任何其他模型方法一樣有效,因此這樣做完全沒問題: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"]
以上程式碼將會告訴 Django,當嘗試在管理介面中依照
colored_first_name
排序時,應依照first_name
欄位排序。若要使用
ordering
引數表示降序排序,您可以在欄位名稱上使用連字號前綴。使用上面的範例,看起來會像這樣:@admin.display(ordering="-first_name") def colored_first_name(self): ...
ordering
引數支援查詢查找,以依照相關模型上的值進行排序。此範例在列表顯示中包含「作者名字」欄位,並允許依名字進行排序: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)
在 Django 5.0 中變更新增了對屬性上
boolean
屬性的支援。list_display
中的欄位名稱也會以 CSS 類別的形式出現在 HTML 輸出中,每個<th>
元素上會是column-<field_name>
的形式。例如,這可以用於在 CSS 檔案中設定欄寬。Django 將會嘗試依照以下順序解譯
list_display
的每個元素:模型中的欄位或相關欄位中的欄位。
可呼叫物件。
表示
ModelAdmin
屬性的字串。表示模型屬性的字串。
例如,如果您有一個名為
first_name
的模型欄位,且同時有一個名為first_name
的ModelAdmin
屬性,將會使用模型欄位。
- ModelAdmin.list_display_links¶
使用
list_display_links
來控制list_display
中的哪些欄位應該連結到物件的「變更」頁面。預設情況下,變更列表頁面會將第一欄(
list_display
中指定的第一個欄位)連結到每個項目的變更頁面。但是list_display_links
允許您變更此行為。將其設定為
None
以完全沒有連結。將其設定為您想要轉換為連結的欄位列表或元組(格式與
list_display
相同)。您可以指定一個或多個欄位。只要這些欄位出現在
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
中 - 一個欄位不能既是表單又是連結。
如果違反了這些規則中的任何一條,您將會收到驗證錯誤。
- ModelAdmin.list_filter¶
設定
list_filter
以啟用管理員變更清單頁面右側邊欄中的篩選器。最簡單的情況下,
list_filter
接受要啟用篩選的欄位名稱的列表或元組,但也提供幾個更進階的選項。有關詳細資訊,請參閱 ModelAdmin 列表篩選器。
- ModelAdmin.list_max_show_all¶
設定
list_max_show_all
以控制在管理員變更清單頁面上的「顯示全部」連結中可以顯示多少項目。只有當總結果計數小於或等於此設定時,管理員才會在變更清單上顯示「顯示全部」連結。預設情況下,此值設定為200
。
- ModelAdmin.list_per_page¶
設定
list_per_page
以控制每個分頁管理員變更清單頁面上顯示多少項目。預設情況下,此值設定為100
。
設定
list_select_related
以告訴 Django 使用select_related()
來檢索管理員變更清單頁面上的物件列表。這可以為您節省大量的資料庫查詢。該值應該是布林值、列表或元組。預設值為
False
。當值為
True
時,將始終呼叫select_related()
。當值設定為False
時,Django 會查看list_display
,如果存在任何ForeignKey
,則會呼叫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()
方法。注意
當已經在變更清單的
QuerySet
上呼叫select_related()
時,ModelAdmin
會忽略此屬性。
- ModelAdmin.ordering¶
設定
ordering
以指定在 Django 管理員檢視中物件列表應如何排序。這應該是一個列表或元組,其格式與模型的ordering
參數相同。如果未提供此設定,Django 管理員將使用模型的預設排序。
如果您需要指定動態排序(例如,根據使用者或語言),您可以實作
get_ordering()
方法。排序和排序的效能考量
為了確保結果的確定性排序,如果變更清單找不到提供完整排序的單個或唯一組合欄位集,它會將
pk
新增至排序中。例如,如果預設排序是按非唯一的
name
欄位排序,則變更清單將按name
和pk
排序。如果您有很多行且在name
和pk
上沒有索引,這可能會導致效能不佳。
- ModelAdmin.paginator¶
用於分頁的分頁器類別。預設情況下,會使用
django.core.paginator.Paginator
。如果自訂分頁器類別沒有與django.core.paginator.Paginator
相同的建構子介面,您還需要為ModelAdmin.get_paginator()
提供實作。
- ModelAdmin.prepopulated_fields¶
設定
prepopulated_fields
為一個字典,將欄位名稱對應到應從中預先填入的欄位class ArticleAdmin(admin.ModelAdmin): prepopulated_fields = {"slug": ["title"]}
設定後,指定的欄位將使用一些 JavaScript 從指定的欄位中填入。此功能的主要用途是從一個或多個其他欄位自動產生
SlugField
欄位的值。產生的值是透過串連來源欄位的值,然後將該結果轉換為有效的 slug(例如,將空格替換為破折號並將 ASCII 字母轉換為小寫字母)而產生的。預先填入的欄位在值儲存後不會被 JavaScript 修改。通常不希望 slugs 變更(如果 slug 在 URL 中使用,這會導致物件的 URL 變更)。
prepopulated_fields
不接受DateTimeField
、ForeignKey
、OneToOneField
和ManyToManyField
欄位。
- ModelAdmin.preserve_filters¶
預設情況下,在建立、編輯或刪除物件後,已套用的篩選器會保留在列表檢視中。您可以將此屬性設定為
False
來清除篩選器。
- ModelAdmin.show_facets¶
- Django 5.0 中的新功能。
控制是否在管理員變更清單中為篩選器顯示面額計數。預設值為
ShowFacets.ALLOW
。顯示時,面額計數會隨著目前套用的篩選器更新。
- class ShowFacets¶
- Django 5.0 中的新功能。
ModelAdmin.show_facets
的允許值的列舉。- 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¶
預設情況下,Django 的管理介面對於
ForeignKey
或已設定choices
的欄位會使用選擇方塊介面 ( <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
是一個ForeignKey
和/或ManyToManyField
欄位的列表,您希望將這些欄位變更為 Select2 自動完成輸入框。預設情況下,管理介面對這些欄位使用選擇方塊介面 (
<select>
)。有時您不希望為了在下拉式選單中顯示所有相關實例而產生額外負擔。Select2 輸入框看起來與預設輸入框類似,但帶有異步載入選項的搜尋功能。如果相關模型有很多實例,這會更快且更易於使用。
您必須在相關物件的
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.count
屬性的預設實作。
- ModelAdmin.raw_id_fields¶
預設情況下,Django 的管理介面對於
ForeignKey
欄位會使用選擇方塊介面 ( <select> )。有時您不希望為了在下拉式選單中顯示所有相關實例而產生額外負擔。raw_id_fields
是一個欄位列表,您希望將這些欄位變更為ForeignKey
或ManyToManyField
的Input
小工具。class ArticleAdmin(admin.ModelAdmin): raw_id_fields = ["newspaper"]
如果欄位是
ForeignKey
,則raw_id_fields
Input
小工具應包含主鍵;如果欄位是ManyToManyField
,則應包含逗號分隔的值列表。raw_id_fields
小工具會在欄位旁邊顯示一個放大鏡按鈕,允許使用者搜尋並選取值。
- ModelAdmin.readonly_fields¶
預設情況下,管理介面會將所有欄位顯示為可編輯。此選項中的任何欄位 (應為
list
或tuple
) 會按原樣顯示其資料且不可編輯;它們也會從用於建立和編輯的ModelForm
中排除。請注意,當指定ModelAdmin.fields
或ModelAdmin.fieldsets
時,唯讀欄位必須存在才能顯示 (否則會被忽略)。如果在沒有透過
ModelAdmin.fields
或ModelAdmin.fieldsets
定義明確排序的情況下使用readonly_fields
,則它們會加在所有可編輯欄位之後。唯讀欄位不僅可以顯示模型欄位的資料,還可以顯示模型的方法或
ModelAdmin
類別本身的方法的輸出。這與ModelAdmin.list_display
的行為非常相似。這提供了一種使用管理介面來提供有關正在編輯的物件狀態的回饋的方式,例如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¶
設定
save_as
以啟用管理變更表單上的「另存為新檔」功能。通常,物件有三個儲存選項:「儲存」、「儲存並繼續編輯」和「儲存並新增另一個」。如果
save_as
為True
,「儲存並新增另一個」將會被「另存為新檔」按鈕取代,該按鈕會建立新物件 (具有新的 ID),而不是更新現有物件。預設情況下,
save_as
設定為False
。
- ModelAdmin.save_as_continue¶
當
save_as=True
時,儲存新物件後的預設重新導向會是該物件的變更檢視。如果將save_as_continue=False
,重新導向將會是變更列表檢視。預設情況下,
save_as_continue
設定為True
。
- ModelAdmin.save_on_top¶
設定
save_on_top
以在您的管理變更表單頂部新增儲存按鈕。通常,儲存按鈕只會出現在表單的底部。如果您設定
save_on_top
,按鈕將會同時出現在頂部和底部。預設情況下,
save_on_top
設定為False
。
- ModelAdmin.search_fields¶
設定
search_fields
以在管理變更列表頁面上啟用搜尋框。這應該設定為一個欄位名稱列表,每當有人在該文字框中提交搜尋查詢時,都會搜尋這些欄位。這些欄位應該是某種文字欄位,例如
CharField
或TextField
。您也可以使用查詢 API 的「follow」標記法在ForeignKey
或ManyToManyField
上執行相關查詢search_fields = ["foreign_key__related_fieldname"]
例如,如果您有一個包含作者的部落格文章,以下定義將允許透過作者的電子郵件地址搜尋部落格文章
search_fields = ["user__email"]
當有人在管理搜尋框中進行搜尋時,Django 會將搜尋查詢分割成單字,並傳回包含每個單字的所有物件 (不區分大小寫,使用
icontains
查詢),其中每個單字都必須至少存在於一個search_fields
中。例如,如果search_fields
設定為['first_name', 'last_name']
,且使用者搜尋john lennon
,Django 會執行相當於此 SQLWHERE
子句的操作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 會執行相當於此 SQLWHERE
子句的操作WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')
如果您不想使用
icontains
作為查詢條件,您可以將任何查詢條件附加到欄位上來使用。例如,您可以透過將search_fields
設定為['first_name__exact']
來使用exact
。有些(較舊的)指定欄位查詢的快捷方式也可用。您可以在
search_fields
中的欄位前加上以下字元,這等同於在該欄位上加上__<lookup>
。前綴
查詢條件
^
=
@
無
如果您需要自訂搜尋功能,可以使用
ModelAdmin.get_search_results()
來提供額外或替代的搜尋行為。
- ModelAdmin.search_help_text¶
設定
search_help_text
以指定搜尋框的說明文字,該文字將顯示在搜尋框下方。
- ModelAdmin.show_full_result_count¶
設定
show_full_result_count
以控制是否要在篩選後的管理頁面上顯示物件的完整計數(例如,99 個結果 (總共 103 個)
)。如果此選項設定為False
,則會顯示類似99 個結果 (顯示全部)
的文字。show_full_result_count=True
的預設值會產生一個查詢,對表格執行完整計數,如果表格包含大量列,這可能會很耗費資源。
- ModelAdmin.sortable_by¶
預設情況下,變更清單頁面允許按照所有模型欄位(以及使用
display()
裝飾器的ordering
參數或具有admin_order_field
屬性的可呼叫物件)進行排序,這些欄位在list_display
中指定。如果您想要停用某些欄位的排序功能,請將
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
自訂範本選項¶
覆寫管理範本 章節說明如何覆寫或擴充預設的管理範本。使用以下選項來覆寫 ModelAdmin
視圖所使用的預設範本。
- ModelAdmin.add_form_template¶
自訂範本的路徑,由
add_view()
使用。
- ModelAdmin.change_form_template¶
自訂範本的路徑,由
change_view()
使用。
- ModelAdmin.change_list_template¶
自訂範本的路徑,由
changelist_view()
使用。
- ModelAdmin.delete_confirmation_template¶
自訂範本的路徑,由
delete_view()
使用,用於在刪除一個或多個物件時顯示確認頁面。
- ModelAdmin.delete_selected_confirmation_template¶
自訂範本的路徑,由
delete_selected
動作方法使用,用於在刪除一個或多個物件時顯示確認頁面。請參閱 動作文件。
- ModelAdmin.object_history_template¶
自訂範本的路徑,由
history_view()
使用。
- ModelAdmin.popup_response_template¶
自訂範本的路徑,由
response_add()
、response_change()
和response_delete()
使用。
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
附加到每個變更的 formset 模型實例,可以這樣做: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()
另請參閱 在 formset 中儲存物件。
警告
所有回傳 ModelAdmin
屬性的 hooks 都會回傳屬性本身,而不是其值的副本。動態修改值可能會導致意想不到的結果。
讓我們以 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
作為參數,並預期回傳一個list
或tuple
,用於排序,類似於ordering
屬性。例如: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
方法會修改顯示的物件列表,使其只包含符合所提供的搜尋詞的物件。它會接收 request、一個套用目前篩選器的 queryset,以及使用者提供的搜尋詞。它會回傳一個包含已修改以實作搜尋的 queryset 的 tuple,以及一個布林值,指出結果是否可能包含重複項目。預設實作會搜尋
ModelAdmin.search_fields
中命名的欄位。可以使用您自己的自訂搜尋方法來覆寫此方法。例如,您可能希望按整數欄位搜尋,或使用外部工具,例如 Solr 或 Haystack。您必須確定您的搜尋方法所實作的 queryset 變更是否可能將重複項目引入結果中,並在回傳值的第二個元素中回傳
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
實例、內嵌 formset 的列表,以及一個布林值,該值基於父級物件是新增還是變更。在這裡,您可以對與父級物件相關的物件執行任何儲存前或儲存後的操作。請注意,此時父級物件及其表單都已儲存。
- ModelAdmin.get_autocomplete_fields(request)¶
get_autocomplete_fields()
方法會接收HttpRequest
,並預期回傳一個list
或tuple
,其中包含將使用自動完成小工具顯示的欄位名稱,如上述ModelAdmin.autocomplete_fields
區段中所述。
- ModelAdmin.get_readonly_fields(request, obj=None)¶
get_readonly_fields
方法會接收HttpRequest
和正在編輯的obj
(在新增表單上則為None
),並預期回傳一個list
或tuple
,其中包含將顯示為唯讀的欄位名稱,如上述ModelAdmin.readonly_fields
區段中所述。
- ModelAdmin.get_prepopulated_fields(request, obj=None)¶
get_prepopulated_fields
方法會接收HttpRequest
和正在編輯的obj
(在新增表單上則為None
),並預期回傳一個dictionary
,如上述ModelAdmin.prepopulated_fields
區段中所述。
- ModelAdmin.get_list_display(request)[原始碼]¶
get_list_display
方法會接收HttpRequest
,並預期回傳一個list
或tuple
,其中包含將在變更清單視圖上顯示的欄位名稱,如上述ModelAdmin.list_display
章節所述。
- ModelAdmin.get_list_display_links(request, list_display)[原始碼]¶
get_list_display_links
方法會接收HttpRequest
和ModelAdmin.get_list_display()
所回傳的list
或tuple
。它預期會回傳None
或一個list
或tuple
,其中包含變更清單中將連結至變更視圖的欄位名稱,如ModelAdmin.list_display_links
章節所述。
- 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 個元素的元組列表,其中每個元組代表管理表單頁面上的<fieldset>
,如上述ModelAdmin.fieldsets
章節所述。
- 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_sortable_by()
方法會接收HttpRequest
,並預期回傳一個集合(例如list
、tuple
或set
),其中包含可在變更清單頁面中排序的欄位名稱。其預設實作會回傳
sortable_by
(如果已設定),否則會延後至get_list_display()
。例如,要防止一或多個欄位排序:
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
物件的list
或tuple
,如下文InlineModelAdmin
章節所述。例如,以下程式碼會回傳 inlines,而不使用預設的根據新增、變更、刪除和檢視權限的篩選: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 是在
inlines
中定義的類別實例,否則您可能會在新增相關物件時遇到「錯誤請求」的錯誤。
- ModelAdmin.get_inlines(request, obj)¶
get_inlines
方法會接收HttpRequest
和正在編輯的obj
(或在新增表單上為None
),並預期回傳一個 inlines 的可迭代物件。您可以覆寫此方法,以根據請求或模型實例動態新增 inlines,而不是在ModelAdmin.inlines
中指定它們。
- ModelAdmin.get_urls()[原始碼]¶
ModelAdmin
上的get_urls
方法會回傳用於該 ModelAdmin 的 URL,其方式與 URLconf 相同。因此,您可以按照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/base_site.html
擴展。{% extends "admin/base_site.html" %} {% block content %} ... {% endblock %}
注意
請注意
self.my_view
函數是如何被包裹在self.admin_site.admin_view
中的。這很重要,因為它可以確保兩件事:執行權限檢查,確保只有活躍的員工使用者才能存取該視圖。
套用
django.views.decorators.cache.never_cache()
裝飾器以防止快取,確保回傳的資訊是最新的。
注意
請注意,自訂模式是包含在常規管理 URL *之前* 的:管理 URL 模式非常寬鬆,幾乎可以匹配任何內容,因此您通常會希望將自訂 URL 添加到內建的 URL 之前。
在此範例中,
my_view
將在/admin/myapp/mymodel/my_view/
處被存取(假設管理 URL 包含在/admin/
)。如果頁面可以快取,但您仍然希望執行權限檢查,您可以傳遞一個
cacheable=True
引數給AdminSite.admin_view()
。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)[原始碼]¶
回傳一個
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)[原始碼]¶
為管理新增和變更視圖回傳 (
FormSet
,InlineModelAdmin
) 配對。例如,如果您只想在變更視圖中顯示特定的 inline,您可以如下覆寫
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
方法允許您覆寫外鍵欄位的預設表單欄位。例如,根據使用者回傳此外鍵欄位的物件子集: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
外鍵欄位,以僅顯示User
實例擁有的汽車。對於更複雜的篩選,您可以使用
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
方法可以被覆寫以變更多對多欄位的預設表單欄位。例如,如果一個擁有者可以擁有多輛汽車,並且汽車可以屬於多個擁有者(一個多對多關係),您可以篩選Car
外鍵欄位,以僅顯示User
擁有的汽車。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)[原始碼]¶
回傳一個
ModelForm
類別,用於變更清單頁面上的Formset
。例如,要使用自訂表單: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 類別。若要使用自訂的 formset,例如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
子類別允許的查找。在 Django 5.0 中變更已新增
request
引數。
- ModelAdmin.has_view_permission(request, obj=None)¶
如果允許檢視
obj
,則應返回True
,否則返回False
。如果 obj 為None
,則應返回True
或False
,以指出是否允許一般檢視此類型的物件(例如,False
將被解釋為表示目前使用者不允許檢視此類型的任何物件)。如果使用者具有「變更」或「檢視」權限,則預設實作會返回
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)¶
如果允許在管理索引頁面上顯示模組並存取模組的索引頁面,則應返回
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
方法會返回一個QuerySet
,其中包含可由管理網站編輯的所有模型實例。覆寫此方法的一個用例是顯示登入使用者擁有的物件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.messages
框架時靜默失敗。這些關鍵字參數與django.contrib.messages.add_message()
的參數一致,詳細資訊請參閱該函式的說明文件。一個差異之處在於,除了整數/常數之外,層級也可以字串標籤的形式傳遞。
- ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)[原始碼]¶
傳回用於此檢視的分頁器實例。預設情況下,會實例化
paginator
的實例。
- ModelAdmin.response_add(request, obj, post_url_continue=None)[原始碼]¶
決定
HttpResponse
對於add_view()
階段。response_add
會在提交管理表單之後,以及在物件和所有相關實例建立並儲存後立即呼叫。您可以覆寫它,以變更物件建立後的預設行為。
- ModelAdmin.response_change(request, obj)[原始碼]¶
決定
HttpResponse
對於change_view()
階段。response_change
會在提交管理表單之後,以及在物件和所有相關實例儲存後立即呼叫。您可以覆寫它,以變更物件變更後的預設行為。
- ModelAdmin.response_delete(request, obj_display, obj_id)[原始碼]¶
決定
HttpResponse
對於delete_view()
階段。response_delete
會在刪除物件之後呼叫。您可以覆寫它,以變更物件刪除後的預設行為。obj_display
是一個字串,其中包含已刪除物件的名稱。obj_id
是用於檢索要刪除物件的序列化識別符。
- ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)[原始碼]¶
一個用於自訂傳遞給表單集建構子的關鍵字參數的 Hook。例如,將
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)[原始碼]¶
管理變更表單的初始資料的 Hook。預設情況下,欄位會從
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()
和「刪除選取」動作的刪除流程的 Hook。objs
參數是要刪除的物件的同質可迭代物件(QuerySet
或模型實例的清單),而request
是HttpRequest
。此方法必須傳回 4 個元素的元組:
(deleted_objects, model_count, perms_needed, protected)
。deleted_objects
是表示所有將要刪除的物件的字串清單。如果有任何相關的物件要刪除,則該清單會是巢狀結構,並且包含這些相關物件。此清單會使用unordered_list
篩選器在範本中格式化。model_count
是一個字典,將每個模型的verbose_name_plural
對應到將要刪除的物件數量。perms_needed
是一個集合,其中包含使用者沒有刪除權限的模型之verbose_name
。protected
是一個字串清單,表示所有無法刪除的受保護相關物件。此清單會顯示在範本中。
其他方法¶
- ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)[原始碼]¶
用於模型實例編輯頁面的 Django 視圖。請參閱下方注意事項。
- ModelAdmin.delete_view(request, object_id, extra_context=None)[原始碼]¶
用於模型實例刪除確認頁面的 Django 視圖。請參閱下方注意事項。
與前一節詳述的 hook 類型的 ModelAdmin
方法不同,這五個方法實際上設計為從管理應用程式 URL 分派處理常式作為 Django 視圖調用,以呈現處理模型實例 CRUD 操作的頁面。因此,完全覆寫這些方法將顯著改變管理應用程式的行為。
覆寫這些方法的常見原因之一是擴充提供給呈現視圖的範本的上下文資料。在以下範例中,覆寫了變更視圖,以便向呈現的範本提供一些原本無法使用的額外映射資料
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 管理 JavaScript 使用 jQuery 函式庫。
為了避免與使用者提供的腳本或函式庫衝突,Django 的 jQuery (版本 3.7.1) 被命名為 django.jQuery
。如果您想在您自己的管理 JavaScript 中使用 jQuery 而無需包含第二份副本,您可以使用變更列表和新增/編輯視圖上的 django.jQuery
物件。此外,您自己的管理表單或依賴 django.jQuery
的 Widget 必須在宣告表單媒體資產時指定 js=['admin/js/jquery.init.js', …]
。
jQuery 已從 3.6.4 升級至 3.7.1。
ModelAdmin
類別預設需要 jQuery,因此除非您有特定需求,否則無需將 jQuery 新增至您的 ModelAdmin
的媒體資源清單中。例如,如果您需要 jQuery 函式庫位於全域命名空間中 (例如在使用第三方 jQuery 外掛程式時),或者如果您需要較新版本的 jQuery,則必須包含您自己的副本。
Django 提供 jQuery 的未壓縮和「最小化」版本,分別為 jquery.js
和 jquery.min.js
。
ModelAdmin
和 InlineModelAdmin
具有 media
屬性,該屬性會傳回儲存表單和/或表單集的 JavaScript 檔案路徑的 Media
物件清單。如果 DEBUG
為 True
,它會傳回各種 JavaScript 檔案的未壓縮版本,包括 jquery.js
;如果不是,則會傳回「最小化」版本。
將自訂驗證新增至管理介面¶
您也可以在管理介面中新增資料的自訂驗證。自動管理介面會重複使用 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[原始碼]¶
管理介面能夠在與父模型相同的頁面上編輯模型。這些稱為內嵌。假設您有這兩個模型
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)
您可以在作者頁面上編輯作者所寫的書籍。您可以在
ModelAdmin.inlines
中指定它們,將內嵌新增至模型from django.contrib import admin class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [ BookInline, ]
Django 提供兩個
InlineModelAdmin
的子類別,它們是這兩者之間的差異僅在於用於呈現它們的範本。
InlineModelAdmin
選項¶
InlineModelAdmin
與 ModelAdmin
共用許多相同的功能,並新增了一些自己的功能 (共用功能實際上是在 BaseModelAdmin
父類別中定義)。共用功能如下
InlineModelAdmin
類別新增或自訂
- InlineModelAdmin.model¶
內嵌正在使用的模型。這是必要的。
- InlineModelAdmin.fk_name¶
模型上外鍵的名稱。在大多數情況下,這會自動處理,但如果有多個外鍵指向同一個父模型,則必須明確指定
fk_name
。
- InlineModelAdmin.formset¶
此屬性的預設值為
BaseInlineFormSet
。使用您自己的 formset 可以提供許多自訂的可能性。內嵌是以 模型表單集合 為基礎建立的。
- InlineModelAdmin.form¶
form
的預設值為ModelForm
。這是當為此內嵌建立 formset 時,傳遞到inlineformset_factory()
的值。
警告
當為 InlineModelAdmin
表單撰寫自訂驗證時,請謹慎撰寫依賴父模型功能的驗證。如果父模型驗證失敗,可能會如 ModelForm 上的驗證 中警告所述,使其處於不一致的狀態。
- InlineModelAdmin.classes¶
一個包含額外 CSS 類別的列表或元組,會應用於為內嵌呈現的 fieldset。預設值為
None
。如同在fieldsets
中設定的類別一樣,具有collapse
類別的內嵌將會使用可展開的小工具來初始折疊。在 Django 5.1 中變更。現在,使用
collapse
類別的fieldsets
會使用<details>
和<summary>
元素,前提是它們定義了name
。
- InlineModelAdmin.extra¶
此屬性控制表單集合除了初始表單外,還會顯示額外表單的數量。預設值為 3。請參閱 表單集合文件 以取得更多資訊。
對於啟用 JavaScript 的瀏覽器使用者,會提供「新增另一個」連結,以便除了使用
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¶
預設情況下,Django 的管理介面對於
ForeignKey
欄位會使用選擇方塊介面 ( <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¶
指定在管理介面中可以變更的內嵌物件是否具有指向變更表單的連結。預設值為
False
。
- InlineModelAdmin.get_formset(request, obj=None, **kwargs)¶
傳回在管理介面新增/變更檢視中使用的
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
管理員新增/變更頁面上顯示內嵌,您需要明確定義外鍵,因為它無法自動執行此操作
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"]
在這個範例中,有兩個值得注意的功能。
首先,MembershipInline
類別參考 Group.members.through
。through
屬性是對管理多對多關係的模型的參考。當您定義多對多欄位時,此模型會由 Django 自動建立。
其次,GroupAdmin
必須手動排除 members
欄位。Django 在定義關係的模型上顯示多對多欄位的管理員小工具(在此範例中,為 Group
)。如果您想使用內嵌模型來表示多對多關係,您必須告訴 Django 管理員「不要」顯示此小工具 - 否則您將在管理員頁面上看到兩個小工具來管理關係。
請注意,當使用此技術時,m2m_changed
訊號不會觸發。這是因為就管理員而言,through
只是一個具有兩個外鍵欄位的模型,而不是多對多關係。
在所有其他方面,InlineModelAdmin
與任何其他模型完全相同。您可以使用任何正常的 ModelAdmin
屬性來自訂外觀。
處理多對多中介模型¶
當您使用 ManyToManyField
的 through
引數指定中介模型時,管理員預設不會顯示小工具。這是因為該中介模型的每個實例都需要比單一小工具中可以顯示的更多資訊,而且多個小工具所需的版面配置會根據中介模型而有所不同。
但是,我們仍然希望能夠內嵌編輯該資訊。幸運的是,我們可以透過內嵌管理模型來執行此操作。假設我們有以下模型
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
值,並將額外新增表單限制為一個。可以使用 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
實例,您可以使用 GenericTabularInline
或 GenericStackedInline
(兩者都是 GenericInlineModelAdmin
的子類別),由 admin
提供。它們分別為代表內嵌物件的表單實作表格和堆疊式視覺版面配置,就像它們的非泛型對應物一樣。它們的行為與任何其他內嵌物件完全相同。在您此範例應用程式的 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 文件。
覆寫管理員範本¶
您可以覆寫管理員模組用於產生管理網站各個頁面的許多範本。您甚至可以針對特定應用程式或特定模型覆寫這些範本中的幾個。
設定專案的管理員範本目錄¶
管理員範本檔案位於 django/contrib/admin/templates/admin 目錄中。
為了覆寫一或多個範本,首先在專案的 templates
目錄中建立一個 admin
目錄。這可以是您在 DIRS
選項中指定的任何目錄,該選項位於 TEMPLATES
設定中的 DjangoTemplates
後端。如果您已自訂 'loaders'
選項,請確保 'django.template.loaders.filesystem.Loader'
出現在 'django.template.loaders.app_directories.Loader'
之前,以便您的自訂範本能被範本載入系統找到,然後才是 django.contrib.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
目錄。
覆寫與取代管理範本¶
由於管理範本的模組化設計,通常不需要也不建議取代整個範本。最好幾乎總是只覆寫您需要變更的範本區段。
繼續上面的範例,我們想要在 Page
模型的「歷史」工具旁邊新增一個新連結。在查看 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 管理站點由
django.contrib.admin.sites.AdminSite
的一個實例表示;預設情況下,這個類別的一個實例會建立為django.contrib.admin.site
,您可以向它註冊您的模型和ModelAdmin
實例。如果您想要自訂預設的管理站點,您可以覆寫它。
在建構
AdminSite
的實例時,您可以使用建構函式的name
引數來提供唯一的實例名稱。這個實例名稱用於識別實例,尤其是在反向管理 URL時。如果未提供實例名稱,則會使用預設實例名稱admin
。有關自訂AdminSite
類別的範例,請參閱自訂 AdminSite 類別。
AdminSite
屬性¶
範本可以覆寫或擴展基本管理範本,如覆寫管理範本中所述。
- AdminSite.site_header¶
在每個管理頁面頂端放置的文字,以
<div>
(字串)。預設情況下,這是「Django 管理」。在 Django 5.0 中變更在舊版本中,
site_header
使用<h1>
標籤。
- AdminSite.site_title¶
在每個管理頁面的
<title>
結尾放置的文字(字串)。預設情況下,這是「Django 網站管理」。
- AdminSite.site_url¶
每個管理頁面頂部的「檢視網站」連結的 URL。預設情況下,
site_url
為/
。將其設定為None
以移除該連結。對於在子路徑上執行的網站,
each_context()
方法會檢查當前請求是否設定了request.META['SCRIPT_NAME']
,如果site_url
未設定為/
以外的值,則使用該值。
- AdminSite.index_title¶
要放在管理首頁頂部的文字(字串)。預設情況下,這是「網站管理」。
- AdminSite.index_template¶
將由管理網站主索引檢視使用的自訂模板路徑。
- AdminSite.app_index_template¶
將由管理網站應用程式索引檢視使用的自訂模板路徑。
- AdminSite.empty_value_display¶
在管理網站的變更列表中顯示空值時要使用的字串。預設為破折號。此值也可以在每個
ModelAdmin
基礎上,以及在ModelAdmin
內的自訂欄位上覆寫,方法是在該欄位上設定empty_value_display
屬性。有關範例,請參閱ModelAdmin.empty_value_display
。
一個布林值,決定是否在較大的螢幕上顯示導覽側邊欄。預設情況下,它設定為
True
。
- AdminSite.final_catch_all_view¶
一個布林值,決定是否在管理介面中新增最終的 catch-all 檢視,將未驗證的使用者重新導向至登入頁面。預設情況下,它設定為
True
。警告
不建議將此設定為
False
,因為此檢視可防止潛在的模型列舉隱私問題。
- AdminSite.login_template¶
將由管理網站登入檢視使用的自訂模板路徑。
- AdminSite.login_form¶
AuthenticationForm
的子類別,將由管理網站登入檢視使用。
- AdminSite.logout_template¶
將由管理網站登出檢視使用的自訂模板路徑。
- AdminSite.password_change_template¶
將由管理網站密碼變更檢視使用的自訂模板路徑。
- AdminSite.password_change_done_template¶
將由管理網站密碼變更完成檢視使用的自訂模板路徑。
AdminSite
方法¶
- AdminSite.each_context(request)[原始碼]¶
傳回要在管理網站中每個頁面的模板內容中放置的變數字典。
預設包含以下變數和值
site_header
:AdminSite.site_header
site_title
:AdminSite.site_title
site_url
:AdminSite.site_url
has_permission
:AdminSite.has_permission()
available_apps
:來自 應用程式註冊表 的應用程式列表,適用於目前使用者。列表中的每個條目都是一個字典,代表一個應用程式,其中包含以下鍵app_label
:應用程式標籤app_url
:管理介面中應用程式索引的 URLhas_module_perms
:一個布林值,指出目前使用者是否允許顯示和存取模組的索引頁面models
:應用程式中可用的模型列表
每個模型都是一個字典,其中包含以下鍵
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
:管理介面中應用程式索引的 URLhas_module_perms
:一個布林值,指出目前使用者是否允許顯示和存取模組的索引頁面models
:應用程式中可用的模型列表name
:應用程式的名稱
每個模型都是一個字典,其中包含以下鍵
model
:模型類別object_name
:模型的類別名稱name
:模型的複數名稱perms
:一個追蹤add
、change
、delete
和view
權限的dict
admin_url
:模型的管理變更列表 URLadd_url
:管理 URL,用於新增新的模型實例
應用程式和模型的列表會按其名稱依字母順序排序。您可以覆寫此方法,以變更管理首頁上的預設順序。
- AdminSite.has_permission(request)[原始碼]¶
如果給定的
HttpRequest
的使用者有權限在管理網站中檢視至少一個頁面,則傳回True
。預設情況下,需要User.is_active
和User.is_staff
都為True
。
- AdminSite.register(model_or_iterable, admin_class=None, **options)[原始碼]¶
使用指定的
admin_class
註冊給定的模型類別(或類別的可迭代物件)。admin_class
預設為ModelAdmin
(預設的管理選項)。如果給定了關鍵字引數(例如list_display
),則會將它們作為選項套用到管理類別。如果模型是抽象的,則會引發
ImproperlyConfigured
,如果模型已註冊,則會引發django.contrib.admin.exceptions.AlreadyRegistered
。
- AdminSite.unregister(model_or_iterable)[原始碼]¶
取消註冊給定的模型類別(或類別的可迭代物件)。
如果模型尚未註冊,則會引發
django.contrib.admin.exceptions.NotRegistered
。
將 AdminSite
實例掛接到您的 URLconf¶
設定 Django 管理介面的最後一步是將您的 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
類別¶
如果您想要使用自訂行為設定自己的管理網站,您可以自由地子類別化 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.apps.SimpleAdminConfig'
而不是 'django.contrib.admin'
。
覆寫預設管理網站¶
您可以透過將自訂 AppConfig
的 default_site
屬性設定為 AdminSite
子類別或傳回網站實例的可呼叫物件的點分隔匯入路徑,來覆寫預設的 django.contrib.admin.site
。
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 中使用多個管理網站¶
您可以在同一個 Django 驅動的網站上建立多個管理網站的實例。建立 AdminSite
的多個實例,並將每個實例放置在不同的 URL 上。
在此範例中,URL /basic-admin/
和 /advanced-admin/
提供管理網站的個別版本 – 分別使用 AdminSite
實例 myproject.admin.basic_site
和 myproject.admin.advanced_site
# 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
時,這才是必要的。
將檢視新增至管理網站¶
就像 ModelAdmin
一樣,AdminSite
也提供可以覆寫的 get_urls()
方法,以定義網站的其他檢視。若要將新的檢視新增至您的管理網站,請擴充基本 get_urls()
方法,以包含新檢視的模式。
注意
任何使用管理範本或擴充基本管理範本的呈現檢視,都應該在呈現範本之前設定 request.current_app
。如果您的檢視位於 AdminSite
上,則應該將其設定為 self.name
,如果您的檢視位於 ModelAdmin
上,則應該將其設定為 self.admin_site.name
。
新增密碼重設功能¶
您可以透過在您的 URLconf 中新增幾行程式碼,將密碼重設功能新增至管理網站。具體來說,新增這四個模式
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/
開頭的 URL 放在包含管理應用程式本身的程式碼行之前)。
存在名為 admin_password_reset
的 URL 將會導致在預設管理登入頁面的密碼方塊下方顯示「忘記密碼?」連結。
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
。例如,要取得透過管理介面進行的所有新增動作列表
from django.contrib.admin.models import ADDITION, LogEntry LogEntry.objects.filter(action_flag=ADDITION)
- LogEntry.change_message¶
修改的詳細描述。例如,在編輯的情況下,此訊息包含已編輯欄位的列表。Django 管理網站將此內容格式化為 JSON 結構,以便
get_change_message()
可以重新組合以目前使用者語言翻譯的訊息。不過,自訂程式碼可能會將其設定為純文字字串。建議使用get_change_message()
方法來擷取此值,而不是直接存取它。
LogEntry
方法¶
- LogEntry.get_change_message()[原始碼]¶
將
change_message
格式化並翻譯成目前使用者語言。在 Django 1.10 之前建立的訊息將始終以記錄時的語言顯示。
反轉管理介面網址¶
當部署 AdminSite
時,可以使用 Django 的 網址反轉系統 來存取該網站提供的檢視。
AdminSite
提供以下命名的網址模式
頁面 |
網址名稱 |
參數 |
---|---|---|
索引 |
|
|
登入 |
|
|
登出 |
|
|
變更密碼 |
|
|
變更密碼完成 |
|
|
i18n JavaScript |
|
|
應用程式索引頁面 |
|
|
重新導向至物件頁面 |
|
|
每個 ModelAdmin
實例都提供一組額外命名的網址
頁面 |
網址名稱 |
參數 |
---|---|---|
變更清單 |
|
|
新增 |
|
|
歷史 |
|
|
刪除 |
|
|
變更 |
|
|
UserAdmin
提供一個命名的網址
頁面 |
網址名稱 |
參數 |
---|---|---|
變更密碼 |
|
|
這些命名的網址使用應用程式命名空間 admin
和與 Site 實例名稱相對應的實例命名空間註冊。
因此 - 如果您想取得預設管理介面中特定 Choice
物件(來自 polls 應用程式)的變更檢視的參考,您可以呼叫
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,))
這將找到已註冊管理應用程式的第一個實例(無論實例名稱是什麼),並解析為該實例中變更 poll.Choice
實例的檢視。
如果您想在特定管理實例中尋找網址,請將該實例的名稱作為 current_app
提示提供給反轉呼叫。例如,如果您特別想要名為 custom
的管理實例中的管理檢視,您需要呼叫
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")
如需更多詳細資訊,請參閱關於 反轉具命名空間網址 的文件。
為了更容易在範本中反轉管理網址,Django 提供了一個 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
實例的網址名稱的最後一部分相符。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')[原始碼]¶
此修飾器用於需要授權的管理檢視。使用此函數修飾的檢視將具有以下行為
如果使用者已登入、是員工 (
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): ...