Django 管理網站

Django 最強大的部分之一是自動管理介面。它會從您的模型讀取元數據,以提供一個快速、以模型為中心的介面,讓受信任的使用者可以管理您網站上的內容。管理介面建議的使用方式僅限於組織的內部管理工具。它不適用於建立您整個前端介面。

管理介面有很多客製化的掛鉤,但請注意不要只嘗試使用這些掛鉤。如果您需要提供一個更以流程為中心的介面,以抽象化資料庫表格和欄位的實作細節,那麼這可能是時候編寫您自己的視圖了。

在本文件中,我們將討論如何啟用、使用和客製化 Django 的管理介面。

總覽

管理介面在 startproject 使用的預設專案範本中啟用。

如果您沒有使用預設專案範本,以下是需求

  1. 'django.contrib.admin' 及其相依性 - django.contrib.authdjango.contrib.contenttypesdjango.contrib.messagesdjango.contrib.sessions - 新增到您的 INSTALLED_APPS 設定。

  2. 在您的 TEMPLATES 設定中,使用 django.template.context_processors.requestdjango.contrib.auth.context_processors.authdjango.contrib.messages.context_processors.messagesOPTIONS'context_processors' 選項中設定 DjangoTemplates 後端。

  3. 如果您已客製化 MIDDLEWARE 設定,則必須包含 django.contrib.sessions.middleware.SessionMiddlewaredjango.contrib.auth.middleware.AuthenticationMiddlewaredjango.contrib.messages.middleware.MessageMiddleware

  4. 將管理介面的 URL 連結到您的 URLconf.

完成這些步驟後,您將可以透過瀏覽您連結的 URL 來使用管理網站(預設為 /admin/)。

如果您需要建立一個使用者來登入,請使用 createsuperuser 命令。預設情況下,登入管理介面需要使用者將 is_staff 屬性設定為 True

最後,判斷您的應用程式的哪些模型應該在管理介面中可編輯。對於每個模型,請依照 ModelAdmin 中的說明,將其註冊到管理介面。

其他主題

另請參閱

有關在生產環境中提供與管理介面關聯的靜態檔案(影像、JavaScript 和 CSS)的資訊,請參閱 提供檔案

有問題嗎?請嘗試 常見問題:管理介面

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()

default_site

預設管理網站的類別或會傳回網站實例的可呼叫物件的虛線匯入路徑。預設值為 'django.contrib.admin.sites.AdminSite'。有關用法,請參閱 覆寫預設管理網站

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

要在變更清單頁面上可用的動作列表。有關詳細資訊,請參閱 管理動作

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 設定為模型中 DateFieldDateTimeField 的名稱,變更清單頁面將包含該欄位的基於日期的向下鑽研導覽。

範例

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 模型的表單,其中只包含 nametitle 欄位,您應該像這樣指定 fieldsexclude

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    fields = ["name", "title"]


class AuthorAdmin(admin.ModelAdmin):
    exclude = ["birth_date"]

由於 Author 模型只有三個欄位,nametitlebirth_date,因此上述宣告產生的表單將包含完全相同的欄位。

ModelAdmin.fields

使用 fields 選項,在「新增」和「變更」頁面上的表單中進行簡單的版面配置變更,例如僅顯示可用欄位的子集、修改其順序或將它們分組為多行。例如,您可以為 django.contrib.flatpages.models.FlatPage 模型定義一個更簡單的管理表單,如下所示

class FlatPageAdmin(admin.ModelAdmin):
    fields = ["url", "title", "content"]

在上面的範例中,表單中只會依序顯示 urltitlecontent 欄位。fields 可以包含在 ModelAdmin.readonly_fields 中定義的值,以只讀方式顯示。

對於更複雜的版面配置需求,請參閱 fieldsets 選項。

fields 選項接受與 list_display 相同的數值類型,但不會接受可呼叫對象和相關欄位的 __ 查詢。模型和模型管理方法名稱只有在它們列在 readonly_fields 中時才會使用。

若要在同一行顯示多個欄位,請將這些欄位包裝在自己的元組中。在此範例中,urltitle 欄位將顯示在同一行,而 content 欄位將在其自己的行中顯示在下方

class FlatPageAdmin(admin.ModelAdmin):
    fields = [("url", "title"), "content"]

可能與 ModelAdmin.fieldsets 選項混淆

這個 fields 選項不應與 fieldsets 選項中的 fields 字典鍵混淆,如下一節所述。

如果沒有 fieldsfieldsets 選項,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"],
            },
        ),
    ]

這會產生一個如下所示的管理頁面

../../../_images/fieldsets.png

如果既沒有 fieldsets 選項,也沒有 fields 選項,Django 會預設顯示每個不是 AutoField 且具有 editable=True 的欄位,並將它們放在一個單一的 fieldset 中,順序與欄位在模型中定義的順序相同。

field_options 字典可以有以下鍵

  • fields

    要在此 fieldset 中顯示的欄位名稱列表或元組。此鍵是必需的。

    範例

    {
        "fields": ["first_name", "last_name", "address", "city", "state"],
    }
    

    fields 選項一樣,若要將多個欄位顯示在同一行,請將這些欄位包裝在它們自己的元組中。在此範例中,first_namelast_name 欄位將顯示在同一行上

    {
        "fields": [("first_name", "last_name"), "address", "city", "state"],
    }
    

    fields 可以包含在 readonly_fields 中定義的值,以顯示為唯讀。

    如果您將可呼叫物件的名稱加入到 fields 中,則與 fields 選項的規則相同:該可呼叫物件必須列在 readonly_fields 中。

  • classes

    包含要應用於 fieldset 的額外 CSS 類別的列表或元組。這可以包括專案中定義的任何自訂 CSS 類別,以及 Django 提供的任何 CSS 類別。在預設的管理站台 CSS 樣式表中,定義了兩個特別有用的類別:collapsewide

    範例

    {
        "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 特殊字元。

TabularInlinefieldsets 的支援有限

fieldsetsTabularInline 搭配使用,功能有限。您可以透過在 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() 方法來自訂預設表單,而不是指定全新的表單。

如需範例,請參閱 在管理介面中新增自訂驗證 一節。

省略 Meta.model 屬性

如果您在 ModelForm 上定義 Meta.model 屬性,您還必須定義 Meta.fields 屬性(或 Meta.exclude 屬性)。但是,由於管理介面有自己的定義欄位方式,因此 Meta.fields 屬性將會被忽略。

如果 ModelForm 只會用於管理介面,最簡單的解決方案是省略 Meta.model 屬性,因為 ModelAdmin 會提供要使用的正確模型。或者,您可以在 Meta 類別中設定 fields = [],以滿足 ModelForm 上的驗證。

ModelAdmin.exclude 具有優先權

如果您的 ModelFormModelAdmin 都定義了 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 以取得詳細資訊。

警告

如果您想要對關聯欄位 (即 ForeignKeyManyToManyField) 使用自訂 widget,請確保您未將該欄位的名稱包含在 raw_id_fieldsradio_fieldsautocomplete_fields 中。

formfield_overrides 不會讓您變更已設定 raw_id_fieldsradio_fieldsautocomplete_fields 的關聯欄位上的 widget。這是因為 raw_id_fieldsradio_fieldsautocomplete_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 將會顯示漂亮的「是」、「否」或「未知」圖示,而不是 TrueFalseNone

  • 如果給定的字串是模型、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 的方法,或傳回 TrueFalseNone 的可呼叫物件,如果您使用 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_nameModelAdmin 屬性,將會使用模型欄位。

使用 list_display_links 來控制 list_display 中的哪些欄位應該連結到物件的「變更」頁面。

預設情況下,變更列表頁面會將第一欄(list_display 中指定的第一個欄位)連結到每個項目的變更頁面。但是 list_display_links 允許您變更此行為。

  • 將其設定為 None 以完全沒有連結。

  • 將其設定為您想要轉換為連結的欄位列表或元組(格式與 list_display 相同)。

    您可以指定一個或多個欄位。只要這些欄位出現在 list_display 中,Django 就不會在意有多少(或多麼少)欄位被連結。唯一的要求是,如果您想以這種方式使用 list_display_links,您必須定義 list_display

在這個範例中,first_namelast_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_editablelist_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 欄位排序,則變更清單將按 namepk 排序。如果您有很多行且在 namepk 上沒有索引,這可能會導致效能不佳。

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 不接受 DateTimeFieldForeignKeyOneToOneFieldManyToManyField 欄位。

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 將改用單選按鈕介面。假設 groupPerson 模型上的 ForeignKey

class PersonAdmin(admin.ModelAdmin):
    radio_fields = {"group": admin.VERTICAL}

您可以選擇使用 django.contrib.admin 模組中的 HORIZONTALVERTICAL

除非欄位是 ForeignKey 或已設定 choices,否則請勿將其包含在 radio_fields 中。

ModelAdmin.autocomplete_fields

autocomplete_fields 是一個 ForeignKey 和/或 ManyToManyField 欄位的列表,您希望將這些欄位變更為 Select2 自動完成輸入框。

預設情況下,管理介面對這些欄位使用選擇方塊介面 (<select>)。有時您不希望為了在下拉式選單中顯示所有相關實例而產生額外負擔。

Select2 輸入框看起來與預設輸入框類似,但帶有異步載入選項的搜尋功能。如果相關模型有很多實例,這會更快且更易於使用。

您必須在相關物件的 ModelAdmin 上定義 search_fields,因為自動完成搜尋會使用它。

為了避免未經授權的資料洩漏,使用者必須擁有相關物件的 viewchange 權限才能使用自動完成功能。

結果的排序和分頁由相關 ModelAdminget_ordering()get_paginator() 方法控制。

在以下範例中,ChoiceAdmin 具有指向 QuestionForeignKey 的自動完成欄位。結果會依 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 是一個欄位列表,您希望將這些欄位變更為 ForeignKeyManyToManyFieldInput 小工具。

class ArticleAdmin(admin.ModelAdmin):
    raw_id_fields = ["newspaper"]

如果欄位是 ForeignKey,則 raw_id_fields Input 小工具應包含主鍵;如果欄位是 ManyToManyField,則應包含逗號分隔的值列表。raw_id_fields 小工具會在欄位旁邊顯示一個放大鏡按鈕,允許使用者搜尋並選取值。

../../../_images/raw_id_fields.png
ModelAdmin.readonly_fields

預設情況下,管理介面會將所有欄位顯示為可編輯。此選項中的任何欄位 (應為 listtuple) 會按原樣顯示其資料且不可編輯;它們也會從用於建立和編輯的 ModelForm 中排除。請注意,當指定 ModelAdmin.fieldsModelAdmin.fieldsets 時,唯讀欄位必須存在才能顯示 (否則會被忽略)。

如果在沒有透過 ModelAdmin.fieldsModelAdmin.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_asTrue,「儲存並新增另一個」將會被「另存為新檔」按鈕取代,該按鈕會建立新物件 (具有新的 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 以在管理變更列表頁面上啟用搜尋框。這應該設定為一個欄位名稱列表,每當有人在該文字框中提交搜尋查詢時,都會搜尋這些欄位。

這些欄位應該是某種文字欄位,例如 CharFieldTextField。您也可以使用查詢 API 的「follow」標記法在 ForeignKeyManyToManyField 上執行相關查詢

search_fields = ["foreign_key__related_fieldname"]

例如,如果您有一個包含作者的部落格文章,以下定義將允許透過作者的電子郵件地址搜尋部落格文章

search_fields = ["user__email"]

當有人在管理搜尋框中進行搜尋時,Django 會將搜尋查詢分割成單字,並傳回包含每個單字的所有物件 (不區分大小寫,使用 icontains 查詢),其中每個單字都必須至少存在於一個 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>

前綴

查詢條件

^

istartswith

=

iexact

@

search

icontains

如果您需要自訂搜尋功能,可以使用 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 的子集合(例如,listtupleset)。空集合會停用所有欄位的排序功能。

如果您需要動態指定此清單,請改為實作 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 作為參數,並預期回傳一個 listtuple,用於排序,類似於 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 中命名的欄位。

可以使用您自己的自訂搜尋方法來覆寫此方法。例如,您可能希望按整數欄位搜尋,或使用外部工具,例如 SolrHaystack。您必須確定您的搜尋方法所實作的 queryset 變更是否可能將重複項目引入結果中,並在回傳值的第二個元素中回傳 True

例如,要按 nameage 搜尋,可以使用:

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,並預期回傳一個 listtuple,其中包含將使用自動完成小工具顯示的欄位名稱,如上述 ModelAdmin.autocomplete_fields 區段中所述。

ModelAdmin.get_readonly_fields(request, obj=None)

get_readonly_fields 方法會接收 HttpRequest 和正在編輯的 obj (在新增表單上則為 None),並預期回傳一個 listtuple,其中包含將顯示為唯讀的欄位名稱,如上述 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,並預期回傳一個 listtuple,其中包含將在變更清單視圖上顯示的欄位名稱,如上述 ModelAdmin.list_display 章節所述。

get_list_display_links 方法會接收 HttpRequestModelAdmin.get_list_display() 所回傳的 listtuple。它預期會回傳 None 或一個 listtuple,其中包含變更清單中將連結至變更視圖的欄位名稱,如 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,並預期回傳一個集合(例如 listtupleset),其中包含可在變更清單頁面中排序的欄位名稱。

其預設實作會回傳 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 物件的 listtuple,如下文 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 中的。這很重要,因為它可以確保兩件事:

  1. 執行權限檢查,確保只有活躍的員工使用者才能存取該視圖。

  2. 套用 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,並透過諸如 fieldsexclude 等屬性進行修改。因此,舉例來說,如果您想為超級使用者提供額外的欄位,您可以像這樣替換不同的基礎表單:

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_foreignkeyformfield_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

省略 Meta.model 屬性

如果在 ModelForm 上定義 Meta.model 屬性,您也必須定義 Meta.fields 屬性(或是 Meta.exclude 屬性)。然而,ModelAdmin 會忽略這個值,並使用 ModelAdmin.list_editable 屬性來覆寫它。最簡單的解決方案是省略 Meta.model 屬性,因為 ModelAdmin 會提供要使用的正確模型。

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,則會引發 DisallowedModelAdminLookupSuspiciousOperation 的子類別)。

預設情況下,lookup_allowed() 允許存取模型的本地欄位、list_filter 中使用的欄位路徑(但不是來自 get_list_filter() 的路徑)以及 limit_choices_toraw_id_fields 中正確運作所需的查找。

覆寫此方法來自訂您的 ModelAdmin 子類別允許的查找。

在 Django 5.0 中變更

已新增 request 引數。

ModelAdmin.has_view_permission(request, obj=None)

如果允許檢視 obj,則應返回 True,否則返回 False。如果 obj 為 None,則應返回 TrueFalse,以指出是否允許一般檢視此類型的物件(例如,False 將被解釋為表示目前使用者不允許檢視此類型的任何物件)。

如果使用者具有「變更」或「檢視」權限,則預設實作會返回 True

ModelAdmin.has_add_permission(request)

如果允許新增物件,則應返回 True,否則返回 False

ModelAdmin.has_change_permission(request, obj=None)

如果允許編輯 obj,則應返回 True,否則返回 False。如果 objNone,則應返回 TrueFalse,以指出是否允許一般編輯此類型的物件(例如,False 將被解釋為表示目前使用者不允許編輯此類型的任何物件)。

ModelAdmin.has_delete_permission(request, obj=None)

如果允許刪除 obj,則應返回 True,否則返回 False。如果 objNone,則應返回 TrueFalse,以指出是否允許一般刪除此類型的物件(例如,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 或模型實例的清單),而 requestHttpRequest

此方法必須傳回 4 個元素的元組:(deleted_objects, model_count, perms_needed, protected)

deleted_objects 是表示所有將要刪除的物件的字串清單。如果有任何相關的物件要刪除,則該清單會是巢狀結構,並且包含這些相關物件。此清單會使用 unordered_list 篩選器在範本中格式化。

model_count 是一個字典,將每個模型的 verbose_name_plural 對應到將要刪除的物件數量。

perms_needed 是一個集合,其中包含使用者沒有刪除權限的模型之 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 視圖。

與前一節詳述的 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_URLNone 則為 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', …]

在 Django 5.0 中變更

jQuery 已從 3.6.4 升級至 3.7.1。

ModelAdmin 類別預設需要 jQuery,因此除非您有特定需求,否則無需將 jQuery 新增至您的 ModelAdmin 的媒體資源清單中。例如,如果您需要 jQuery 函式庫位於全域命名空間中 (例如在使用第三方 jQuery 外掛程式時),或者如果您需要較新版本的 jQuery,則必須包含您自己的副本。

Django 提供 jQuery 的未壓縮和「最小化」版本,分別為 jquery.jsjquery.min.js

ModelAdminInlineModelAdmin 具有 media 屬性,該屬性會傳回儲存表單和/或表單集的 JavaScript 檔案路徑的 Media 物件清單。如果 DEBUGTrue,它會傳回各種 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 TabularInline[原始碼]
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 選項

InlineModelAdminModelAdmin 共用許多相同的功能,並新增了一些自己的功能 (共用功能實際上是在 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 是一個欄位列表,您希望將這些欄位變更為 ForeignKeyManyToManyFieldInput 小工具。

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

指定在管理介面中可以變更的內嵌物件是否具有指向變更表單的連結。預設值為 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,否則傳回 Falseobj 是正在編輯的父物件,或者在新增新父物件時為 None

InlineModelAdmin.has_change_permission(request, obj=None)

如果允許編輯內嵌物件,則應傳回 True,否則傳回 Falseobj 是正在編輯的父物件。

InlineModelAdmin.has_delete_permission(request, obj=None)

如果允許刪除內嵌物件,則應傳回 True,否則傳回 Falseobj 是正在編輯的父物件。

注意

傳遞給 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.throughthrough 屬性是對管理多對多關係的模型的參考。當您定義多對多欄位時,此模型會由 Django 自動建立。

其次,GroupAdmin 必須手動排除 members 欄位。Django 在定義關係的模型上顯示多對多欄位的管理員小工具(在此範例中,為 Group)。如果您想使用內嵌模型來表示多對多關係,您必須告訴 Django 管理員「不要」顯示此小工具 - 否則您將在管理員頁面上看到兩個小工具來管理關係。

請注意,當使用此技術時,m2m_changed 訊號不會觸發。這是因為就管理員而言,through 只是一個具有兩個外鍵欄位的模型,而不是多對多關係。

在所有其他方面,InlineModelAdmin 與任何其他模型完全相同。您可以使用任何正常的 ModelAdmin 屬性來自訂外觀。

處理多對多中介模型

當您使用 ManyToManyFieldthrough 引數指定中介模型時,管理員預設不會顯示小工具。這是因為該中介模型的每個實例都需要比單一小工具中可以顯示的更多資訊,而且多個小工具所需的版面配置會根據中介模型而有所不同。

但是,我們仍然希望能夠內嵌編輯該資訊。幸運的是,我們可以透過內嵌管理模型來執行此操作。假設我們有以下模型

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 類別可用的任何選項來自訂此設定。

現在,為 PersonGroup 模型建立管理員檢視

class PersonAdmin(admin.ModelAdmin):
    inlines = [MembershipInline]


class GroupAdmin(admin.ModelAdmin):
    inlines = [MembershipInline]

最後,向管理網站註冊您的 PersonGroup 模型

admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)

現在,您的管理網站已設定為從 PersonGroup 詳細資料頁面內嵌編輯 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 實例,您可以使用 GenericTabularInlineGenericStackedInline (兩者都是 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_templateAdminSite.login_templateAdminSite.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 類別

django.contrib.admin.sites.all_sites

一個 WeakSet 包含所有管理站點實例。

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

AdminSite.enable_nav_sidebar

一個布林值,決定是否在較大的螢幕上顯示導覽側邊欄。預設情況下,它設定為 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:管理介面中應用程式索引的 URL

    • has_module_perms:一個布林值,指出目前使用者是否允許顯示和存取模組的索引頁面

    • models:應用程式中可用的模型列表

    每個模型都是一個字典,其中包含以下鍵

    • model:模型類別

    • object_name:模型的類別名稱

    • name:模型的複數名稱

    • perms:一個追蹤 addchangedeleteview 權限的 dict

    • admin_url:模型的管理變更列表 URL

    • add_url:管理 URL,用於新增新的模型實例

  • is_popup:目前頁面是否顯示在彈出視窗中

  • is_nav_sidebar_enabledAdminSite.enable_nav_sidebar

  • log_entriesAdminSite.get_log_entries()

AdminSite.get_app_list(request, app_label=None)[原始碼]

傳回來自 應用程式註冊表 的應用程式列表,適用於目前使用者。您可以選擇性地傳遞 app_label 引數以取得單個應用程式的詳細資料。列表中的每個條目都是一個字典,代表一個應用程式,其中包含以下鍵

  • app_label:應用程式標籤

  • app_url:管理介面中應用程式索引的 URL

  • has_module_perms:一個布林值,指出目前使用者是否允許顯示和存取模組的索引頁面

  • models:應用程式中可用的模型列表

  • name:應用程式的名稱

每個模型都是一個字典,其中包含以下鍵

  • model:模型類別

  • object_name:模型的類別名稱

  • name:模型的複數名稱

  • perms:一個追蹤 addchangedeleteview 權限的 dict

  • admin_url:模型的管理變更列表 URL

  • add_url:管理 URL,用於新增新的模型實例

應用程式和模型的列表會按其名稱依字母順序排序。您可以覆寫此方法,以變更管理首頁上的預設順序。

AdminSite.has_permission(request)[原始碼]

如果給定的 HttpRequest 的使用者有權限在管理網站中檢視至少一個頁面,則傳回 True。預設情況下,需要 User.is_activeUser.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.get_model_admin(model)[原始碼]
Django 5.0 中的新功能。

傳回給定模型類別的管理類別。如果模型尚未註冊,則會引發 django.contrib.admin.exceptions.NotRegistered

AdminSite.get_log_entries(request)[原始碼]
Django 5.0 中的新功能。

傳回相關 LogEntry 實例的查詢集,顯示在網站索引頁面上。可以覆寫此方法以按其他條件篩選日誌項目。

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'

覆寫預設管理網站

您可以透過將自訂 AppConfigdefault_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_sitemyproject.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

記錄的動作類型:ADDITIONCHANGEDELETION

例如,要取得透過管理介面進行的所有新增動作列表

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_edited_object()[原始碼]

一個返回所引用物件的快捷方式。

LogEntry.get_change_message()[原始碼]

change_message 格式化並翻譯成目前使用者語言。在 Django 1.10 之前建立的訊息將始終以記錄時的語言顯示。

反轉管理介面網址

當部署 AdminSite 時,可以使用 Django 的 網址反轉系統 來存取該網站提供的檢視。

AdminSite 提供以下命名的網址模式

頁面

網址名稱

參數

索引

index

登入

login

登出

logout

變更密碼

password_change

變更密碼完成

password_change_done

i18n JavaScript

jsi18n

應用程式索引頁面

app_list

app_label

重新導向至物件頁面

view_on_site

content_type_idobject_id

每個 ModelAdmin 實例都提供一組額外命名的網址

頁面

網址名稱

參數

變更清單

{{ app_label }}_{{ model_name }}_changelist

新增

{{ app_label }}_{{ model_name }}_add

歷史

{{ app_label }}_{{ model_name }}_history

object_id

刪除

{{ app_label }}_{{ model_name }}_delete

object_id

變更

{{ app_label }}_{{ model_name }}_change

object_id

UserAdmin 提供一個命名的網址

頁面

網址名稱

參數

變更密碼

auth_user_password_change

user_id

這些命名的網址使用應用程式命名空間 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_labelmodel_name 屬性的任何物件,通常由目前模型的管理檢視提供。

display 修飾器

display(*, boolean=None, ordering=None, description=None, empty_value=None)[原始碼]

此修飾器可用於設定自訂顯示函數的特定屬性,這些函數可以與 list_displayreadonly_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): ...
回到頂端