Django站點管理——管理站點
參考文獻:
https://docs.djangoproject.com/zh-hans/2.0/ref/contrib/admin/
Django的admin站點
Django最強大的部分之一是自動管理界面。 它從您的模型中讀取元數據,以提供快速,以模型為中心的界面,受信任的用戶可以在其中管理您網站上的內容。 管理員的建議用途僅限於組織的內部管理工具。 它不是用於構建整個前端。
管理員有許多用於自定義的鉤子,但要註意嘗試專門使用這些鉤子。 如果您需要提供一個更加以流程為中心的接口來抽象出數據庫表和字段的實現細節,那麽可能是時候編寫自己的視圖了。
在本文檔中,我們將討論如何激活,使用和自定義Django的管理界面。
概覽
在startproject使用的默認項目模板中啟用了admin。
供參考,以下是要求:
- 將“django.contrib.admin”添加到INSTALLED_APPS設置中。
- 管理員有四個依賴項 - django.contrib.auth,django.contrib.contenttypes,django.contrib.messages和django.contrib.sessions。 如果這些應用程序不在您的INSTALLED_APPS列表中,請添加它們。
- 將django.contrib.auth.context_processors.auth和Django.contrib.messages.context_processors.messages添加到TEMPLATES中定義的DjangoTemplates後端的‘context_processors‘選項以及django.contrib.auth.middleware.AuthenticationMiddleware和Django.contrib.messages。 middleware.MessageMiddleware到MIDDLEWARE。 默認情況下這些都是活動的,因此如果您手動調整設置,則只需執行此操作。
- 確定應在管理界面中編輯哪些應用程序模型。
- 對於每個模型,可以選擇創建一個ModelAdmin類,該類封裝了該特定模型的自定義管理功能和選項。
- 實例化AdminSite並告訴它每個模型和ModelAdmin類。
- 將AdminSite實例掛鉤到您的URLconf中。
完成這些步驟後,您將能夠通過訪問您將其掛鉤到的URL(/ admin /,默認情況下)來使用您的Django管理站點。 如果需要創建要登錄的用戶,可以使用createsuperuser命令。
其他要點:
- Admin actions
- The Django admin documentation generator
- JavaScript customizations in the admin
ModelAdmin 對象
class ModelAdmin
ModelAdmin類是管理界面中模型的表示。 通常,這些文件存儲在應用程序中名為admin.py的文件中。 讓我們看一下ModelAdmin的一個非常簡單的例子:
from django.contrib import admin from myproject.myapp.models import Author class AuthorAdmin(admin.ModelAdmin): pass admin.site.register(Author, AuthorAdmin)
當然,如果你只想用默認的,不需要自定制的話,那麽只需做以下操作即可:
from django.contrib import admin from myproject.myapp.models import Author admin.site.register(Author)
寄存器裝飾器
register(*models, site=django.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)。
admin文件的搜索
當您在INSTALLED_APPS設置中放入‘django.contrib.admin‘時,Django會自動在每個應用程序中查找管理模塊並將其導入。
class apps.AdminConfig
這是admin的默認AppConfig類。 它在Django啟動時調用autodiscover()。
class apps.SimpleAdminConfig
此類的工作方式與AdminConfig類似,不同之處在於它不調用autodiscover()。
autodiscover()
此函數嘗試在每個已安裝的應用程序中導入管理模塊。 預計此類模塊將向管理員註冊模型。
通常,您不需要直接調用此函數,因為當Django啟動時AdminConfig會調用它。
如果您使用的是自定義AdminSite,則通常會將所有ModelAdmin子類導入代碼並將其註冊到自定義AdminSite。 在這種情況下,為了禁用auto-discover()功能,您應該在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設置為模型中DateField或DateTimeField的名稱,更改列表頁面將包含該字段的基於日期的向下鉆取導航。
例如:
date_hierarchy = ‘pub_date‘
您還可以使用__查找在相關模型上指定字段,例如:
date_hierarchy = ‘author__pub_date‘
這將基於可用數據智能地填充自身,例如, 如果所有日期都在一個月內,它將僅顯示日級向下鉆取。
註意:date_hierarchy在內部使用QuerySet.datetimes()。 啟用時區支持(USE_TZ = True)時,請參閱其文檔以了解一些註意事項。
ModelAdmin.empty_value_display
此屬性會覆蓋記錄的空字段(無,空字符串等)的默認顯示值。 默認值為 - (破折號)。 例如:
from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): empty_value_display = ‘-empty-‘
您還可以使用AdminSite.empty_value_display覆蓋所有管理頁面的empty_value_display,或者對於以下特定字段:
from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): fields = (‘name‘, ‘title‘, ‘view_birth_date‘) def view_birth_date(self, obj): return obj.birth_date view_birth_date.empty_value_display = ‘???‘
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,您可以指定字段或排除如下:
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將按順序顯示在表單中。 字段可以包含在ModelAdmin.readonly_fields中定義的值,以顯示為只讀。有關更復雜的布局需求,請參閱fieldsets選項。
與list_display不同,fields選項可能只包含模型上的字段名稱或表單指定的表單。 它只有在readonly_fields中列出時才包含callable。
要在同一行上顯示多個字段,請將這些字段包裝在自己的元組中。 在此示例中,url和title字段將顯示在同一行上,content字段將顯示在它們自己的行下方:
class FlatPageAdmin(admin.ModelAdmin): fields = ((‘url‘, ‘title‘), ‘content‘)
註意:不應將此字段選項與fieldsets選項中的字段字典鍵混淆,如下一節中所述。
如果既沒有字段也沒有字段集選項,Django將默認顯示除AutoField外的每個字段,並且在單個字段集中具有editable = True,其順序與模型中定義的字段的順序相同。
ModelAdmin.fieldsets
設置字段集以控制管理“添加”和“更改”頁面的布局。
fieldsets是兩元組的列表,其中每個二元組表示管理表單頁面上的<fieldset>。 (<fieldset>是表單的“部分”。)
兩元組的格式為(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,其順序與模型中定義的字段的順序相同。
field_options字典可以包含以下鍵:
- fields
-
要在此字段集中顯示的字段名稱元組。 這個鍵是必需的。
例:
{ ‘fields‘: (‘first_name‘, ‘last_name‘, ‘address‘, ‘city‘, ‘state‘), }
與fields選項一樣,要在同一行上顯示多個字段,請將這些字段包裝在自己的元組中。 在此示例中,first_name和last_name字段將顯示在同一行上:
{ ‘fields‘: ((‘first_name‘, ‘last_name‘), ‘address‘, ‘city‘, ‘state‘), }
字段可以包含在readonly_fields中定義的值,以顯示為只讀。
如果將可調用的名稱添加到字段,則應用與fields選項相同的規則:callable必須在readonly_fields中列出。
-
- classes
-
包含要應用於fieldset的額外CSS類的列表或元組。
例:
{ ‘classes‘: (‘wide‘, ‘extrapretty‘), }
默認管理站點樣式表定義的兩個有用的類是折疊和寬泛的。 具有折疊樣式的字段集最初將在管理員中折疊,並替換為小的“單擊以展開”鏈接。 具有寬樣式的場集將被賦予額外的水平空間。
-
- description
-
一組可選的額外文本,顯示在每個字段集的頂部,位於字段集的標題下。 由於其布局,此字符串不會為TabularInline呈現。
請註意,當該值顯示在管理界面中時,該值不會被HTML轉義。 如果您願意,可以包含HTML。 或者,您可以使用純文本和django.utils.html.escape()來轉義任何HTML特殊字符。
-
ModelAdmin.filter_horizontal
默認情況下,管理站點中會顯示一個帶有<select multiple>的ManyToManyField。 但是,在選擇多個項目時,多選框可能難以使用。 將ManyToManyField添加到此列表將改為使用一個漂亮的不顯眼的JavaScript“過濾器”界面,允許在選項中進行搜索。 未選擇和選定的選項並排顯示在兩個框中。 請參閱filter_vertical以使用垂直界面。
ModelAdmin.filter_vertical
與filter_horizontal相同,但使用過濾器界面的垂直顯示,並在所選選項框上方顯示未選中的選項框。
ModelAdmin.form
默認情況下,會為您的模型動態創建ModelForm。 它用於創建添加/更改頁面上顯示的表單。 您可以輕松提供自己的ModelForm來覆蓋添加/更改頁面上的任何默認表單行為。 或者,您可以使用ModelAdmin.get_form()方法自定義默認表單,而不是指定一個全新表單。
有關示例,請參閱向管理員添加自定義驗證部分。
註意:
如果在ModelForm上定義Meta.model屬性,則還必須定義Meta.fields屬性(或Meta.exclude屬性)。 但是,由於管理員有自己的定義字段的方式,因此將忽略Meta.fields屬性。
如果ModelForm僅用於管理員,最簡單的解決方案是省略Meta.model屬性,因為ModelAdmin將提供正確的模型以供使用。 或者,您可以在Meta類中設置fields = []以滿足ModelForm上的驗證。
註意:
如果ModelForm和ModelAdmin都定義了排除選項,則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最常見的用途是為特定類型的字段添加自定義窗口小部件。 因此,假設我們編寫了一個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 __()方法。 有關詳細信息,請參閱Forms API。
警告:
如果要使用具有關系字段的自定義窗口小部件(即ForeignKey或ManyToManyField),請確保未在raw_id_fields,radio_fields或autocomplete_fields中包含該字段的名稱。
formfield_overrides不允許您更改設置了raw_id_fields,radio_fields或autocomplete_fields的關系字段上的窗口小部件。 那是因為raw_id_fields,radio_fields和autocomplete_fields意味著他們自己的自定義小部件。
ModelAdmin.inlines
請參閱下面的InlineModelAdmin對象以及ModelAdmin.get_formsets_with_inlines()。
ModelAdmin.list_display
設置list_display以控制在管理員的更改列表頁面上顯示的字段。
例如:
list_display = (‘first_name‘, ‘last_name‘)
如果未設置list_display,則管理站點將顯示一個列,該列顯示每個對象的__str __()表示形式。
您可以在list_display中使用四個可能的值:
- 模型的一個字段,如下:
-
class PersonAdmin(admin.ModelAdmin): list_display = (‘first_name‘, ‘last_name‘)
-
- 可調用,接受模型實例的一個參數, 如下:
-
def upper_case_name(obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = ‘Name‘ class PersonAdmin(admin.ModelAdmin): list_display = (upper_case_name,)
-
- 表示ModelAdmin上的屬性的字符串, 這與可調用的行為相同, 如下:
-
class PersonAdmin(admin.ModelAdmin): list_display = (‘upper_case_name‘,) def upper_case_name(self, obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = ‘Name‘
-
- 表示模型上屬性的字符串。 這與callable幾乎相同,但在此上下文中self是模型實例, 如下:
-
from django.contrib import admin from django.db import models class Person(models.Model): name = models.CharField(max_length=50) birthday = models.DateField() def decade_born_in(self): return self.birthday.strftime(‘%Y‘)[:3] + "0‘s" decade_born_in.short_description = ‘Birth decade‘ class PersonAdmin(admin.ModelAdmin): list_display = (‘name‘, ‘decade_born_in‘)
-
關於list_display的一些特殊情況需要註意:
-
如果該字段是ForeignKey,Django將顯示相關對象的__str __()。
-
不支持ManyToManyField字段,因為這將需要為表中的每一行執行單獨的SQL語句。 如果您想要這樣做,請為您的模型提供自定義方法,並將該方法的名稱添加到list_display。 (有關list_display中自定義方法的更多信息,請參閱下文。)
-
如果該字段是BooleanField或NullBooleanField,Django將顯示一個漂亮的“開”或“關”圖標而不是True或False。
-
如果給定的字符串是模型,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) 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方法時,您可以通過向可調用對象添加short_description屬性來自定義列的標題。
-
如果字段的值為None,空字符串或不帶元素的iterable,則Django將顯示 - (破折號)。 您可以使用AdminSite.empty_value_display覆蓋它:
from django.contrib import admin admin.site.empty_value_display = ‘(None)‘
您還可以使用ModelAdmin.empty_value_display:
class PersonAdmin(admin.ModelAdmin): empty_value_display = ‘unknown‘
或者在字段級別:
class PersonAdmin(admin.ModelAdmin): list_display = (‘name‘, ‘birth_date_view‘) def birth_date_view(self, obj): return obj.birth_date birth_date_view.empty_value_display = ‘unknown‘
如果給定的字符串是模型的方法,ModelAdmin或返回True或False Djallo的callable將顯示一個漂亮的“on”或“off”圖標,如果你給該方法一個值為True的布爾屬性。
這是一個完整的示例模型:
from django.contrib import admin from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) birthday = models.DateField() def born_in_fifties(self): return self.birthday.strftime(‘%Y‘)[:3] == ‘195‘ born_in_fifties.boolean = True class PersonAdmin(admin.ModelAdmin): list_display = (‘name‘, ‘born_in_fifties‘)
__str __()方法在list_display中與任何其他模型方法一樣有效,因此完全可以這樣做:
list_display = (‘__str__‘, ‘some_other_field‘)
通常,list_display的元素不是實際的數據庫字段,不能用於排序(因為Django在數據庫級別進行所有排序)。
但是,如果list_display的元素表示某個數據庫字段,則可以通過設置該項的admin_order_field屬性來指示此事實。
例如:
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) def colored_first_name(self): return format_html( ‘<span style="color: #{};">{}</span>‘, self.color_code, self.first_name, ) colored_first_name.admin_order_field = ‘first_name‘ class PersonAdmin(admin.ModelAdmin): list_display = (‘first_name‘, ‘colored_first_name‘)
當嘗試按照管理員中的colored_first_name排序時,上面將告訴Django按first_name字段排序。
要使用admin_order_field指示降序,可以在字段名稱上使用連字符前綴。 使用上面的示例,這看起來像:
colored_first_name.admin_order_field = ‘-first_name‘
admin_order_field支持查詢查找以按相關模型上的值排序。 此示例在列表顯示中包含“作者名字”列,並允許按名字對其進行排序:
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‘) def author_first_name(self, obj): return obj.author.first_name author_first_name.admin_order_field = ‘author__first_name‘
list_display的元素也可以是屬性。 但請註意,由於屬性在Python中的工作方式,只有在使用property()函數而不是@property裝飾器時才能在屬性上設置short_description。
例如:
class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) def my_property(self): return self.first_name + ‘ ‘ + self.last_name my_property.short_description = "Full name of the person" full_name = property(my_property) class PersonAdmin(admin.ModelAdmin): list_display = (‘full_name‘,)
list_display中的字段名稱也將在HTML輸出中顯示為CSS類,每個<th>元素上的column- <field_name>形式。 例如,這可用於在CSS文件中設置列寬。
Django將嘗試按此順序解釋list_display的每個元素:
- A field of the model.
- A callable.
- A string representing a
ModelAdmin
attribute. - A string representing a model attribute.
例如,如果您將first_name作為模型字段和ModelAdmin屬性,則將使用模型字段。
ModelAdmin.list_display_links
使用list_display_links來控制list_display中的if和which字段是否應鏈接到對象的“change”頁面。
默認情況下,更改列表頁面會將第一列(list_display中指定的第一個字段)鏈接到每個項目的更改頁面。 但是list_display_links讓你改變這個:
- 將其設置為無來取消鏈接。
- 將其設置為要轉換為鏈接的列的列表或字段元組(格式與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
InlineModelAdmin對象
重寫admin模板
AdminSite對象
LogEntry對象
反向解析admin的URL
staff_member_required 裝飾器
Django站點管理——管理站點