Django最强大的部分之一是自动管理界面。它从模型中读取元数据,以提供一个快速的、以模型为中心的界面,在该界面中,受信任的用户可以管理您站点上的内容。管理员建议的使用仅限于组织的内部管理工具。它不是用来构建整个前端的。
管理员有许多用于定制的钩子,但是要小心尝试专门使用这些钩子。如果您需要提供一个更以流程为中心的接口来抽象数据库表和字段的实现细节,那么可能是时候编写自己的视图了。
在本文档中,我们将讨论如何激活、使用和自定义Django的管理界面。
在使用的默认项目模板中启用了管理员 startproject
.
如果不使用默认项目模板,则需要满足以下要求:
添加 'django.contrib.admin'
及其依赖性- django.contrib.auth
, django.contrib.contenttypes
, django.contrib.messages
和 django.contrib.sessions
-给你 INSTALLED_APPS
设置。
配置 DjangoTemplates
后台 TEMPLATES
设置与 django.template.context_processors.request
, django.contrib.auth.context_processors.auth
,以及 django.contrib.messages.context_processors.messages
在 'context_processors'
选择 OPTIONS
。
如果你已经定制了 MIDDLEWARE
设置, django.contrib.auth.middleware.AuthenticationMiddleware
和 django.contrib.messages.middleware.MessageMiddleware
必须包括在内。
完成这些步骤后,您可以通过访问链接到的URL来使用管理网站。 (/admin/
默认情况下)。
如果您需要创建用户来登录,请使用 createsuperuser
命令默认情况下,登录管理员需要用户具有 is_staff
属性设置为 True
。
最后,确定在管理界面中哪些应用程序模型应该是可编辑的。对于这些模型中的每一个,请向管理员注册它们,如中所述。 ModelAdmin
.
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
decorator¶也有一个装饰符注册您的 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)
.
当你放 'django.contrib.admin'
在你 INSTALLED_APPS
设置,Django自动查找 admin
并导入每个应用程序中的模块。
这是默认值 AppConfig
管理类。它叫 autodiscover()
当姜戈开始的时候。
这个班的工作原理是 AdminConfig
,除非它不叫 autodiscover()
.
此函数尝试导入 admin
每个已安装应用程序中的模块。这些模块需要向管理员注册模型。
通常,您不需要将此函数直接调用为 AdminConfig
当Django启动时调用它。
如果使用自定义 AdminSite
,导入所有 ModelAdmin
子类到代码中,并将它们注册到自定义 AdminSite
. 在这种情况下,为了禁用自动发现,您应该 'django.contrib.admin.apps.SimpleAdminConfig'
而不是 'django.contrib.admin'
在你 INSTALLED_APPS
设置。
ModelAdmin
选项¶这个 ModelAdmin
非常灵活。它有几个处理自定义界面的选项。所有选项都定义在 ModelAdmin
子类::
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = "pub_date"
控制操作栏在页面上的显示位置。默认情况下,管理更改列表在页面顶部显示操作 (actions_on_top = True; actions_on_bottom = False
)
控制是否在操作下拉列表旁边显示选择计数器。默认情况下,管理更改列表将显示它 (actions_selection_counter = True
)
集合 date_hierarchy
以…的名义 DateField
或 DateTimeField
在您的模型中,更改列表页面将包含该字段基于日期的向下导航。
例子::
date_hierarchy = "pub_date"
还可以使用 __
查找,例如:
date_hierarchy = "author__pub_date"
这将基于可用数据智能地填充自身,例如,如果所有日期都在一个月内,则只显示日级别的向下钻取。
备注
date_hierarchy
使用 QuerySet.datetimes()
内部的。启用时区支持时,请参阅其文档以了解一些注意事项。 (USE_TZ = True
)
此属性覆盖记录字段为空的默认显示值 (None
,空字符串等)。默认值为 -
(破折号)例如::
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
empty_value_display = "-empty-"
您还可以覆盖 empty_value_display
所有管理页面 AdminSite.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
如果给定该属性,则该属性应该是要从表单中排除的字段名列表。
例如,让我们考虑以下模型:
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"]
由于作者模型只有三个字段, name
, title
和 birth_date
,由上述声明生成的表单将包含完全相同的字段。
使用 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
选项不应与 fields
字典键 fieldsets
选项,如下一节所述。
如果既不 fields
也不 fieldsets
存在选项,Django将默认显示非 AutoField
并且有 editable=True
在单个字段集中,与在模型中定义的字段顺序相同。
集合 fieldsets
控制管理“添加”和“更改”页面的布局。
fieldsets
是一个二元组列表,其中每个二元组表示一个 <fieldset>
在管理表单页面上。(A) <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
在单个字段集中,与在模型中定义的字段顺序相同。
这个 field_options
字典可以有以下键:
fields
要在此字段集中显示的字段名称列表或元组。此密钥是必需的。
例子::
{
"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
包含应用于字段集的额外CSS类的列表或数组。这可以包括项目中定义的任何自定义CSS类,以及Django提供的任何CSS类。在默认的管理站点CSS样式表中,定义了两个特别有用的类: collapse
和 wide
。
例子::
{
"classes": ["wide", "collapse"],
}
现场设置 wide
样式将在管理界面中获得额外的横向空间。带有名称和 collapse
样式最初将折叠,使用具有切换功能的可扩展小部件来切换其可见性。
fieldsets
使用 collapse
类现在使用 <details>
和 <summary>
元素,前提是它们定义了 name
。
description
将显示在每个字段集顶部、字段集标题下的可选额外文本字符串。
注意这个值是 not HTML在管理界面中显示时被转义。如果您愿意,这允许您包含HTML。或者,您可以使用纯文本和 django.utils.html.escape()
以转义任何HTML特殊字符。
TabularInline
has limited
support for fieldsets
vbl.使用 fieldsets
使用 TabularInline
功能有限。您可以指定将显示哪些字段及其在 TabularInline
通过定义布局 fields
在 field_options
字典。
不支持所有其他功能。这包括使用 name
为一组字段定义标题。
默认情况下,A ManyToManyField
在管理站点中显示 <select multiple>
. 但是,在选择多个项目时,很难使用多个选择框。添加一个 ManyToManyField
对于这个列表,将使用一个漂亮的、不引人注目的javascript“过滤器”接口,允许在选项中进行搜索。未选定和选定的选项并排显示在两个框中。见 filter_vertical
使用垂直界面。
等同于 filter_horizontal
,但使用过滤器界面的垂直显示,未选定选项框显示在选定选项框的上方。
默认情况下 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
在上面的示例中,“年龄”字段将被排除,但“名称”字段将包含在生成的表单中。
这提供了一种快速而肮脏的方法来覆盖 Field
用于管理的选项。 formfield_overrides
是一个字典,将字段类映射到要在构造时传递给字段的参数dict。
因为这有点抽象,我们来看一个具体的例子。最常用的 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},
}
注意字典中的键是实际的字段类, not 一个字符串。该值是另一个字典;这些参数将传递到表单域的 __init__()
方法。见 表单API 有关详细信息。
警告
如果您想将自定义小部件与关系字段(即 ForeignKey
或 ManyToManyField
)确保您没有将该字段的名称包含在 raw_id_fields
, radio_fields
或 autocomplete_fields
.
formfield_overrides
不允许您更改关系字段的小部件 raw_id_fields
, radio_fields
或 autocomplete_fields
集合。那是因为 raw_id_fields
, radio_fields
和 autocomplete_fields
暗示自己的自定义小部件。
见 InlineModelAdmin
以及下面的对象 ModelAdmin.get_formsets_with_inlines()
.
集合 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"]
支持使用 __
当针对相关字段时,添加了查找。
需要注意的几个特殊情况 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
,空字符串或不带元素的iterable,将显示django -
(破折号)您可以用覆盖此 AdminSite.empty_value_display
::
from django.contrib import admin
admin.site.empty_value_display = "(None)"
您也可以使用 ModelAdmin.empty_value_display
::
class PersonAdmin(admin.ModelAdmin):
empty_value_display = "unknown"
或在字段级别:
class PersonAdmin(admin.ModelAdmin):
list_display = ["name", "birth_date_view"]
@admin.display(empty_value="unknown")
def birth_date_view(self, obj):
return obj.birth_date
如果给出的字符串是模型的方法, ModelAdmin
或返回的可调用 True
, False
,或 None
,如果您用 display()
装修师通过 boolean
值设置为的参数 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()
@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 first_name
试图排序时的字段 colored_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
Query expressions 可用于 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()
功能和 not 这个 @property
必须使用装饰器::
def my_property(self):
return self.first_name + " " + self.last_name
my_property.short_description = "Full name of the person"
my_property.admin_order_field = "last_name"
my_property.boolean = False
full_name = property(my_property)
中的字段名 list_display
也将以CSS类的形式出现在HTML输出中 column-<field_name>
在每一个 <th>
元素。例如,这可以用于设置CSS文件中的列宽。
Django将尝试解释 list_display
按此顺序:
模型的字段或相关字段。
可赎回的
一个表示 ModelAdmin
属性。
表示模型属性的字符串。
例如,如果你有 first_name
作为模型字段和 ModelAdmin
属性,将使用模型字段。
使用 list_display_links
控制if和哪个字段 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
集合 list_editable
到模型上允许在“更改列表”页上编辑的字段名称列表。也就是说,列在 list_editable
将在更改列表页面上显示为表单小部件,允许用户一次编辑和保存多行。
备注
list_editable
以特定方式与其他几个选项交互;您应该注意以下规则:
任何字段 list_editable
也必须在 list_display
. 不能编辑未显示的字段!
不能同时列出同一字段 list_editable
和 list_display_links
--字段不能既是表单又是链接。
如果这些规则中的任何一个被破坏,您将得到一个验证错误。
集 list_filter
激活管理员更改列表页面右侧边栏中的过滤器。
在最简单的情况下 list_filter
采用要激活筛选的字段名称的列表或元组,但有几个更高级的选项可用。看见 ModelAdmin 列表过滤器 详情请看。
集合 list_max_show_all
控制“全部显示”管理更改列表页上可以显示多少项。只有当总结果计数小于或等于此设置时,管理员才会在更改列表上显示“全部显示”链接。默认情况下,此值设置为 200
.
集合 list_per_page
控制每个分页管理更改列表页上显示的项目数。默认情况下,此值设置为 100
.
集合 list_select_related
告诉Django使用 select_related()
在“管理更改列表”页上检索对象列表时。这可以为您节省大量的数据库查询。
值应该是布尔值、列表或元组。默认是 False
.
当价值是 True
, select_related()
将始终被调用。当值设置为 False
,Django会看 list_display
并调用 select_related()
如果有的话 ForeignKey
是存在的。
如果需要更细粒度的控制,请使用元组(或列表)作为 list_select_related
. 空元组将阻止Django调用 select_related
完全。任何其他元组都将直接传递给 select_related
作为参数。例如::
class ArticleAdmin(admin.ModelAdmin):
list_select_related = ["author", "category"]
将调用 select_related('author', 'category')
.
如果需要根据请求指定动态值,可以实现 get_list_select_related()
方法。
备注
ModelAdmin
当时,忽略此属性 select_related()
已经被召集到了变革者的 QuerySet
。
集合 ordering
指定如何在Django管理视图中排列对象列表。这应该是与模型的列表或元组格式相同的列表或元组 ordering
参数。
如果没有提供,django管理员将使用模型的默认排序。
如果需要指定动态顺序(例如,取决于用户或语言),可以实现 get_ordering()
方法。
排序和排序时的性能考虑
为了确保结果的确定顺序,变更列表添加了 pk
如果找不到提供总排序的单个或唯一字段集,则返回排序。
例如,如果默认的排序方式是非唯一的 name
字段,然后更改列表按 name
和 pk
. 如果您有很多行并且没有索引,这可能会执行得很差。 name
和 pk
.
要用于分页的分页器类。默认情况下, django.core.paginator.Paginator
使用。如果自定义paginator类与 django.core.paginator.Paginator
,您还需要为 ModelAdmin.get_paginator()
.
集合 prepopulated_fields
到字典,将字段名映射到它应预填充的字段::
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ["title"]}
设置后,给定字段将使用一点JavaScript从分配的字段填充。该功能的主要用途是自动生成 SlugField
来自一个或多个其他字段的字段。生成的值是通过连接源字段的值,然后将结果转换为有效的小块(例如,用破折号代替空白和大写的ASCI字母)来生成的。
保存值后,javascript不会修改预填充字段。通常不希望slug更改(如果在其中使用了slug,则会导致对象的url更改)。
prepopulated_fields
不接受 DateTimeField
, ForeignKey
, OneToOneField
和 ManyToManyField
领域。
默认情况下,创建、编辑或删除对象后,应用的过滤器会保留在列表视图中。您可以通过将此属性设置为来清除过滤器 False
。
控制是否为管理员更改列表中的筛选器显示方面计数。默认为 ShowFacets.ALLOW
。
显示时,小平面计数将根据当前应用的过滤器进行更新。
的允许值的枚举 ModelAdmin.show_facets
。
始终显示小平面计数。
在以下情况下显示小平面计数 _facets
提供了查询字符串参数。
切勿显示小平面计数。
集 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
要完全禁用镶嵌面,请执行以下操作。
默认情况下,Django的管理员将选择框界面(<select>)用于以下字段: ForeignKey
或有 choices
集合。如果字段存在于 radio_fields
,Django将使用一个单选按钮界面。假设 group
是一个 ForeignKey
上 Person
型号:
class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}
你可以选择使用 HORIZONTAL
或 VERTICAL
从 django.contrib.admin
模块。
不包括字段 radio_fields
除非它是 ForeignKey
或有 choices
集合。
autocomplete_fields
是一个列表 ForeignKey
和/或 ManyToManyField
要更改为的字段 Select2 自动完成输入。
默认情况下,管理员使用选择框界面 (<select>
)对于那些领域。有时,您不希望在下拉列表中选择要显示的所有相关实例的开销。
select2输入看起来类似于默认输入,但带有一个异步加载选项的搜索功能。如果相关模型有多个实例,这将更快、更方便用户使用。
你必须定义 search_fields
在相关对象上 ModelAdmin
因为自动完成搜索使用它。
为了避免未经授权的数据泄漏,用户必须 view
或 change
对相关对象的权限,以便使用自动完成功能。
结果的排序和分页由相关的 ModelAdmin
的 get_ordering()
和 get_paginator()
方法。
在下面的示例中, ChoiceAdmin
有一个自动完成字段用于 ForeignKey
到 Question
. 结果按筛选 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
财产。
默认情况下,Django的管理员将选择框界面(<select>)用于以下字段: ForeignKey
. 有时,您不希望产生必须选择要在下拉列表中显示的所有相关实例的开销。
raw_id_fields
是要更改为 Input
任何一个的小部件 ForeignKey
或 ManyToManyField
::
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ["newspaper"]
这个 raw_id_fields
Input
如果字段是 ForeignKey
如果字段是 ManyToManyField
. 这个 raw_id_fields
小部件在字段旁边显示放大镜按钮,允许用户搜索和选择值:
默认情况下,管理员将所有字段显示为可编辑。此选项中的任何字段(应为 list
或 tuple
)将其数据显示为“是”且不可编辑;它们也从 ModelForm
用于创建和编辑。请注意,当指定 ModelAdmin.fields
或 ModelAdmin.fieldsets
只读字段必须存在才能显示(否则将被忽略)。
如果 readonly_fields
在不定义显式排序方式的情况下使用 ModelAdmin.fields
或 ModelAdmin.fieldsets
它们将最后添加到所有可编辑字段之后。
只读字段不仅可以显示模型字段中的数据,还可以显示模型方法或 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>")
集合 save_as
在管理更改窗体上启用“另存为新”功能。
通常,对象有三个保存选项:“保存”、“保存并继续编辑”和“保存并添加另一个”。如果 save_as
是 True
“保存并添加另一个”将替换为“另存为新”按钮,该按钮创建新对象(具有新ID),而不是更新现有对象。
默认情况下, save_as
设置为 False
.
什么时候? save_as=True
,保存新对象后的默认重定向是指向该对象的更改视图。如果你设置 save_as_continue=False
,重定向将指向变更列表视图。
默认情况下, save_as_continue
设置为 True
.
集合 save_on_top
在管理更改表单的顶部添加保存按钮。
通常,保存按钮只出现在表单的底部。如果你设置 save_on_top
,按钮将同时出现在顶部和底部。
默认情况下, save_on_top
设置为 False
.
集合 search_fields
启用“管理更改列表”页上的搜索框。这应该设置为每当有人在该文本框中提交搜索查询时将搜索的字段名列表。
这些字段应该是某种文本字段,例如 CharField
或 TextField
. 您还可以对 ForeignKey
或 ManyToManyField
使用lookup api“follow”表示法:
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
作为查找,您可以将任何查找附加到字段中。例如,您可以使用 exact
通过设置 search_fields
到 ['first_name__exact']
.
还提供了一些用于指定字段查找的(旧的)快捷方式。您可以在 search_fields
包含以下字符,相当于添加 __<lookup>
现场:
前缀 |
查找 |
---|---|
^ |
|
= |
|
@ |
|
没有 |
如果需要自定义搜索,可以使用 ModelAdmin.get_search_results()
提供附加或备用搜索行为。
集 search_help_text
若要指定将显示在其下方的搜索框的描述性文本,请执行以下操作。
集合 show_full_result_count
控制是否应在已筛选的管理页面(例如 99 results (103 total)
)如果此选项设置为 False
一个文本 99 results (Show all)
而是显示。
默认的 show_full_result_count=True
生成一个查询以对表执行完全计数,如果表包含大量行,这可能会很昂贵。
默认情况下,更改列表页面允许按所有模型字段(以及使用 ordering
参数设置为 display()
装饰师或拥有 admin_order_field
属性)中指定 list_display
。
如果要禁用某些列的排序,请设置 sortable_by
收藏(例如 list
, tuple
或 set
)的子集 list_display
你想分类的。空集合禁用所有列的排序。
如果需要动态指定此列表,请实现 get_sortable_by()
方法。
集合 view_on_site
控制是否显示“现场查看”链接。此链接应将您带到一个URL,您可以在其中显示保存的对象。
该值可以是布尔标志,也可以是可调用的。如果 True
(默认),对象的 get_absolute_url()
方法将用于生成URL。
如果你的模型有 get_absolute_url()
方法,但不希望出现“View on site”按钮,只需设置 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
意见:
自定义模板的路径,由使用 add_view()
.
自定义模板的路径,由使用 change_view()
.
自定义模板的路径,由使用 changelist_view()
.
自定义模板的路径,由使用 delete_view()
用于在删除一个或多个对象时显示确认页。
自定义模板的路径,由 delete_selected
删除一个或多个对象时显示确认页的操作方法。见 actions documentation .
自定义模板的路径,由使用 history_view()
.
自定义模板的路径,由使用 response_add()
, response_change()
和 response_delete()
.
ModelAdmin
方法¶警告
当超越 ModelAdmin.save_model()
和 ModelAdmin.delete_model()
,您的代码必须保存/删除该对象。它们不是为了否决的目的,而是允许您执行额外的操作。
这个 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)
这个 delete_model
方法给出了 HttpRequest
以及一个模型实例。重写此方法允许执行删除前或删除后操作。调用 super().delete_model()
要删除对象,请使用 Model.delete()
.
这个 delete_queryset()
方法给出了 HttpRequest
和A QuerySet
要删除的对象。重写此方法以自定义“删除选定对象”的删除过程 action .
这个 save_formset
方法给出了 HttpRequest
父母 ModelForm
实例和基于添加或更改父对象的布尔值。
例如,要附加 request.user
到每个已更改的表单集模型实例::
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
也见 在表单集中保存对象 .
这个 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"]
这个 get_search_results
方法修改显示为与提供的搜索词匹配的对象的列表。它接受请求、应用当前过滤器的查询集和用户提供的搜索词。它返回一个包含为实现搜索而修改的查询集的元组,以及一个指示结果是否可能包含重复项的布尔值。
默认实现搜索 ModelAdmin.search_fields
.
此方法可能会被您自己的自定义搜索方法覆盖。例如,您可能希望按整型字段进行搜索,或使用外部工具,如 Solr 或 Haystack 。您必须确定您的搜索方法实现的查询集更改是否会在结果中引入重复项,并返回 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')
例如,它会对数值字段进行字符串比较 ... OR UPPER("polls_choice"."votes"::text) = UPPER('4')
在PostgreSQL上。
这个 save_related
方法给出了 HttpRequest
父母 ModelForm
实例、内联表单集列表和基于父级是添加还是更改的布尔值。在这里,您可以为与父级相关的对象执行任何保存前或保存后操作。请注意,此时父对象及其窗体已经保存。
这个 get_autocomplete_fields()
方法给出了 HttpRequest
并期望返回 list
或 tuple
的字段名,将使用自动完成小部件显示,如上文中所述。 ModelAdmin.autocomplete_fields
部分。
这个 get_readonly_fields
方法给出了 HttpRequest
以及 obj
正在编辑(或 None
并将返回 list
或 tuple
将显示为只读的字段名,如上文中所述 ModelAdmin.readonly_fields
部分。
这个 get_prepopulated_fields
方法给出了 HttpRequest
以及 obj
正在编辑(或 None
并将返回 dictionary
,如上所述 ModelAdmin.prepopulated_fields
部分。
这个 get_list_display
方法给出了 HttpRequest
并期望返回 list
或 tuple
将在ChangeList视图中显示的字段名,如上文中所述。 ModelAdmin.list_display
部分。
这个 get_list_display_links
方法给出了 HttpRequest
以及 list
或 tuple
返回的 ModelAdmin.get_list_display()
. 预计它将返回 None
或A list
或 tuple
更改列表中将链接到更改视图的字段名,如中所述。 ModelAdmin.list_display_links
部分。
这个 get_exclude
方法给出了 HttpRequest
以及 obj
正在编辑(或 None
在“添加”窗体上),并将返回字段列表,如中所述。 ModelAdmin.exclude
.
这个 get_fields
方法给出了 HttpRequest
以及 obj
正在编辑(或 None
在“添加”窗体上),并将返回字段列表,如上文中所述 ModelAdmin.fields
部分。
这个 get_fieldsets
方法被赋予了 HttpRequest
以及 obj
正在编辑(或 None
在Add窗体上),并预期返回一个二元组列表,其中每个二元组表示一个 <fieldset>
在管理表单页面上,如 ModelAdmin.fieldsets
一节。
这个 get_list_filter
方法给出了 HttpRequest
并将返回与 list_filter
属性。
这个 get_list_select_related
方法给出了 HttpRequest
并应返回布尔值或列表作为 ModelAdmin.list_select_related
做。
这个 get_search_fields
方法给出了 HttpRequest
并将返回与 search_fields
属性。
这个 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"}
这个 get_inline_instances
方法给出了 HttpRequest
以及 obj
正在编辑(或 None
并将返回 list
或 tuple
属于 InlineModelAdmin
对象,如下所述 InlineModelAdmin
部分。例如,下面将返回不带基于添加、更改、删除和查看权限的默认筛选的内联::
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
或者在添加相关对象时可能会遇到“错误请求”错误。
这个 get_inlines
方法被赋予了 HttpRequest
以及 obj
正在编辑(或 None
在添加表单上)并预计返回内联行的可迭代对象。您可以重写此方法以根据请求或模型实例动态添加内联行,而不是在 ModelAdmin.inlines
。
这个 get_urls
对象上的方法 ModelAdmin
以与URLconf相同的方式返回要用于该ModelAdmin的URL。因此,您可以扩展它们,如中所述 URL调度器 ,使用 AdminSite.admin_view()
您的视图的包装::
from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super().get_urls()
my_urls = [path("my_view/", self.admin_site.admin_view(self.my_view))]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
如果要使用管理布局,请从 admin/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
属性。
返回A 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
直接上课。
产量 (FormSet
, InlineModelAdmin
)用于管理添加和更改视图的对。
例如,如果只想在更改视图中显示特定的内联,则可以重写 get_formsets_with_inlines
如下:
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline, SomeOtherInline]
def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if not isinstance(inline, MyInline) or obj is not None:
yield inline.get_formset(request, obj), inline
这个 formfield_for_foreignkey
A方法 ModelAdmin
允许您重写外键字段的默认FormField。例如,要基于用户返回此外键字段的对象子集,请执行以下操作:
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
像 formfield_for_foreignkey
方法 formfield_for_manytomany
方法可以重写以更改多对多字段的默认FormField。例如,如果一个车主可以拥有多辆车,并且车可以属于多个车主——多对多关系——那么您可以过滤 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)
像 formfield_for_foreignkey
和 formfield_for_manytomany
方法, formfield_for_choice_field
方法可以重写以更改已声明选项的字段的默认FormField。例如,如果超级用户可用的选项应与普通员工可用的选项不同,则可以按以下步骤进行操作:
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
在保存前验证模型本身。
返回 Changelist
用于列出的类。默认情况下, django.contrib.admin.views.main.ChangeList
使用。通过继承这个类,您可以更改列表的行为。
返回A ModelForm
在中使用的类 Formset
在变更列表页上。要使用自定义表单,例如:
from django import forms
class MyForm(forms.ModelForm):
pass
class MyModelAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs):
return MyForm
返回A ModelFormSet 在ChangeList页上使用的类,如果 list_editable
使用。要使用自定义表单集,例如:
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)
更改列表页中的对象可以通过从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
子类。
应该返回 True
如果查看 obj
是允许的, False
否则。如果OBJ是 None
应该回归 True
或 False
指示一般情况下是否允许查看此类型的对象(例如, False
将解释为当前用户不允许查看任何此类对象)。
默认实现返回 True
如果用户具有“更改”或“查看”权限。
应该返回 True
如果允许添加对象, False
否则。
应该返回 True
中频编辑 obj
是允许的, False
否则。如果 obj
是 None
应该回归 True
或 False
指示一般情况下是否允许编辑此类型的对象(例如, False
将被解释为当前用户不允许编辑此类型的任何对象)。
应该返回 True
如果删除 obj
是允许的, False
否则。如果 obj
是 None
应该回归 True
或 False
指示一般情况下是否允许删除此类型的对象(例如, False
将被解释为当前用户不允许删除此类型的任何对象)。
应该返回 True
如果允许在管理索引页上显示模块并访问模块的索引页, False
否则。使用 User.has_module_perms()
默认情况下。覆盖它不会限制对视图、添加、更改或删除视图的访问, has_view_permission()
, has_add_permission()
, has_change_permission()
和 has_delete_permission()
应该用来做那个。
这个 get_queryset
A方法 ModelAdmin
返回A 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)
使用向用户发送消息 django.contrib.messages
后端。见 custom ModelAdmin example .
关键字参数允许您更改消息级别、添加额外的CSS标记,或者在 contrib.messages
未安装框架。这些关键字参数与 django.contrib.messages.add_message()
,有关详细信息,请参阅该函数的文档。一个区别是,除了整数/常量之外,级别还可以作为字符串标签传递。
返回要用于此视图的分页器的实例。默认情况下,实例化 paginator
.
决定 HttpResponse
对于 add_view()
阶段。
response_add
在提交管理表单之后,以及在创建和保存对象和所有相关实例之后调用。创建对象后,可以重写它以更改默认行为。
决定 HttpResponse
对于 change_view()
阶段。
response_change
在提交管理表单之后以及保存对象和所有相关实例之后调用。您可以在对象更改后重写它以更改默认行为。
决定 HttpResponse
对于 delete_view()
阶段。
response_delete
在删除对象后调用。删除对象后,可以重写它以更改默认行为。
obj_display
是一个具有已删除对象名称的字符串。
obj_id
是用于检索要删除的对象的序列化标识符。
用于定制传递给形式集构造函数的关键字参数的挂钩。例如,要通过 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
用于表单集表单。
管理变更表单上初始数据的挂钩。默认情况下,字段的初始值来自 GET
参数。例如, ?name=initial_value
将设置 name
字段的初始值为 initial_value
.
此方法应返回表单中的字典 {{'fieldname': 'fieldval'}}
::
def get_changeform_initial_data(self, request):
return {"name": "custom_initial_value"}
一个钩子,用于自定义 delete_view()
以及“删除所选内容” action .
这个 objs
参数是对象的同构不可迭代(a QuerySet
或要删除的模型实例列表),以及 request
是 HttpRequest
.
此方法必须返回 (deleted_objects, model_count, perms_needed, protected)
.
deleted_objects
是表示将被删除的所有对象的字符串列表。如果有任何相关对象要删除,则列表将嵌套并包含这些相关对象。列表在模板中使用 unordered_list
过滤器。
model_count
是一个字典映射每个模型的 verbose_name_plural
删除的对象数。
perms_needed
是一组 verbose_name
用户没有删除权限的模型的。
protected
是表示无法删除的所有受保护相关对象的字符串列表。列表将显示在模板中。
模型实例编辑页的Django视图。见下面的注释。
不同于钩子类型 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 documentation .
ModelAdmin
资产定义¶有时您希望在添加/更改视图中添加一些CSS和/或javascript。这可以通过使用 Media
你的内部阶级 ModelAdmin
::
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ["my_styles.css"],
}
js = ["my_code.js"]
这个 staticfiles app 预置 STATIC_URL
(或) MEDIA_URL
如果 STATIC_URL
是 None
)任何资产路径。同样的规则也适用于 regular asset definitions on forms .
django管理javascript使用 jQuery 类库。
为了避免与用户提供的脚本或库冲突,Django的jQuery(版本3.7.1)被命名为 django.jQuery
。如果您想在您自己的管理脚本中使用jQuery而不包括第二个副本,您可以使用 django.jQuery
对象并添加/编辑视图。此外,您自己的管理表单或小部件取决于 django.jQuery
必须指定 js=['admin/js/jquery.init.js', …]
什么时候 declaring form media assets 。
这个 ModelAdmin
类默认需要jquery,因此不需要将jquery添加到 ModelAdmin
的媒体资源列表,除非您有特定需求。例如,如果您要求jquery库位于全局命名空间中(例如使用第三方jquery插件时),或者如果您需要较新版本的jquery,则必须包含自己的副本。
django提供jquery的未压缩和“小型”版本,如 jquery.js
和 jquery.min.js
分别。
ModelAdmin
和 InlineModelAdmin
有一个 media
返回的列表的属性 Media
存储窗体和/或窗体集的javascript文件路径的对象。如果 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
否则,事情可能会破裂。见 forms 文件 custom validation 更具体地说, model form validation notes 更多信息。
InlineModelAdmin
对象¶管理界面能够在与父模型相同的页面上编辑模型。这些被称为入口。假设您有这两种型号:
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
类添加或自定义:
内联使用的模型。这是必需的。
模型上的外键的名称。在大多数情况下,这将自动处理,但是 fk_name
如果同一父模型有多个外键,则必须显式指定。
默认为 BaseInlineFormSet
. 使用您自己的表单集可以为您提供许多自定义的可能性。周围建有进水口 model formsets .
价值 form
默认为 ModelForm
. 这是传递给 inlineformset_factory()
为该内联创建表单集时。
警告
为编写自定义验证时 InlineModelAdmin
对于依赖父模型特性的验证,请谨慎编写。如果父模型未能验证,则它可能处于不一致状态,如中的警告所述。 A的验证 ModelForm .
包含额外CSS类的列表或数组,以应用于为内联行呈现的字段集。默认为 None
.与中配置的类一样 fieldsets
,与一条直线 collapse
类最初将使用可扩展小部件折叠。
fieldsets
使用 collapse
类现在使用 <details>
和 <summary>
元素,前提是它们定义了 name
。
这控制了除了初始表单之外,表单集将显示的额外表单的数量。切换到3。看到 formsets documentation 以获取更多信息。
对于启用了javascript的浏览器的用户,提供了一个“添加另一个”链接,以便除了由于 extra
参数。
如果当前显示的表单数超过 max_num
或者如果用户没有启用javascript。
InlineModelAdmin.get_extra()
还允许您自定义额外表单的数量。
这将控制要在内联中显示的最大表单数。这与对象数量没有直接关联,但如果值足够小,则可以关联。见 限制可编辑对象的数量 更多信息。
InlineModelAdmin.get_max_num()
还允许您自定义最大数量的额外表单。
这将控制要在内联中显示的最小表单数。见 modelformset_factory()
更多信息。
InlineModelAdmin.get_min_num()
还允许您自定义所显示表单的最小数目。
默认情况下,Django的管理员将选择框界面(<select>)用于以下字段: ForeignKey
. 有时,您不希望产生必须选择要在下拉列表中显示的所有相关实例的开销。
raw_id_fields
是要更改为 Input
任何一个的小部件 ForeignKey
或 ManyToManyField
::
class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ["pages"]
用于在页面上呈现内联的模板。
属性的重写 verbose_name
从模特的内心 Meta
班级。
属性的重写 verbose_name_plural
从模特的内心 Meta
班级。如果没有给出这一点,并且 InlineModelAdmin.verbose_name
定义后,Django将使用 InlineModelAdmin.verbose_name
+ 's'
。
指定是否可以在内联中删除内联对象。默认为 True
.
指定可在管理员中更改的内联对象是否具有指向更改表单的链接。默认为 False
.
返回A BaseInlineFormSet
类,用于管理添加/更改视图。 obj
正在编辑父对象还是 None
添加新父级时。参见示例 ModelAdmin.get_formsets_with_inlines
.
返回要使用的额外内联表单数。默认情况下,返回 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.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.min_num
属性。
重写此方法以编程方式确定内联窗体的最小数目。例如,这可能基于模型实例(作为关键字参数传递 obj
)
应该返回 True
如果允许添加内联对象, False
否则。 obj
正在编辑父对象还是 None
添加新父级时。
应该返回 True
如果允许编辑内联对象, False
否则。 obj
正在编辑的父对象。
应该返回 True
如果允许删除内联对象, False
否则。 obj
正在编辑的父对象。
备注
这个 obj
参数传递给 InlineModelAdmin
方法是正在编辑的父对象,或者 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的管理员 not 显示这个小部件-否则您将在管理关系的管理页面上得到两个小部件。
请注意,使用此技术时, m2m_changed
信号不会触发。这是因为在行政方面, through
只是一个具有两个外键字段的模型,而不是多对多关系。
在所有其他方面, InlineModelAdmin
和其他的完全一样。您可以使用任何标准 ModelAdmin
性质。
当您使用 through
对A的论证 ManyToManyField
默认情况下,管理员不会显示小部件。这是因为该中间模型的每个实例需要的信息比单个小部件中显示的信息多,并且多个小部件所需的布局将因中间模型的不同而不同。
然而,我们仍然希望能够在线编辑该信息。幸运的是,我们可以通过内联管理模型做到这一点。假设我们有以下模型::
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
此示例使用默认值 InlineModelAdmin
值 Membership
模型,并将额外的添加表单限制为一个。这可以使用任何可用的选项进行定制 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)
现在您的管理站点设置为编辑 Membership
对象从 Person
或 Group
详细页面。
可以将内联与一般相关的对象一起使用。假设您有以下型号:
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)
如果要允许编辑和创建 Image
实例上 Product
,添加/更改可使用的视图 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 documentation 更具体的信息。
您可以重写管理模块用来生成管理网站各个页面的许多模板。您甚至可以针对特定应用程序或特定型号重写其中一些模板。
管理模板文件位于 django/contrib/admin/templates/admin 目录。
为了覆盖其中的一个或多个,首先创建 admin
项目中的目录 templates
目录。这可以是您在 DIRS
选择权 DjangoTemplates
后端在 TEMPLATES
设置。如果你已经定制了 '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
我们项目的目录。
由于管理模板的模块化设计,通常不需要也不建议替换整个模板。最好只覆盖模板中需要更改的部分。
要继续上面的示例,我们希望在 History
工具 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
目录,我们的链接将显示在我的应用程序中所有型号的更改表单上。
不是每个模板都在 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 %}
。
extrabody
块¶您可以添加自定义HTML、JavaScript或其他内容以在关闭前显示 </body>
扩展的模板标签 admin/base.html
通过扩展 extrabody
块例如,如果您希望在页面加载时出现警报,您可以添加 admin/base.html
将模板覆盖到项目:
{% extends 'admin/base.html' %}
{% block extrabody %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
window.alert('Welcome!');
});
</script>
{% endblock extrabody %}
AdminSite
对象¶Django管理站点由以下实例表示: django.contrib.admin.sites.AdminSite
;默认情况下,此类的实例创建为 django.contrib.admin.site
你可以注册你的模型 ModelAdmin
实例。
如果要自定义默认管理网站,可以 override it .
在构造 AdminSite
,您可以使用 name
构造函数的参数。此实例名称用于标识实例,尤其是在 reversing admin URLs . 如果未提供实例名称,则默认实例名称为 admin
将被使用。见 定制 AdminSite 类 例如自定义 AdminSite
类。
AdminSite
属性¶模板可以覆盖或扩展基本管理模板,如中所述。 覆盖管理模板 .
要放在每个管理页面顶部的文本,如 <div>
(字符串)。默认情况下,这是“Django管理”。
要放在每个管理页末尾的文本 <title>
(字符串)默认情况下,这是“Django站点管理”。
每个管理页面顶部的“查看站点”链接的URL。默认情况下, site_url
is /
. Set it to `` none``删除链接。
对于在子路径上运行的站点, each_context()
方法检查当前请求是否具有 request.META['SCRIPT_NAME']
如果 site_url
不是设置为 /
.
要放在管理索引页顶部的文本(字符串)。默认情况下,这是“网站管理”。
管理网站主索引视图将使用的自定义模板的路径。
管理网站应用程序索引视图将使用的自定义模板的路径。
用于在管理网站的更改列表中显示空值的字符串。默认为短划线。该值也可以在Per上重写 ModelAdmin
基于自定义字段 ModelAdmin
通过设置 empty_value_display
字段的属性。见 ModelAdmin.empty_value_display
举个例子。
布尔值,确定是否在较大屏幕上显示导航侧边栏。默认情况下,它设置为 True
。
布尔值,确定是否向管理员添加最终的全面视图,该管理员将未经身份验证的用户重定向到登录页面。默认情况下,它设置为 True
。
警告
将其设置为 False
不建议这样做,因为该视图可以防止潜在的模型列举隐私问题。
管理网站登录视图将使用的自定义模板的路径。
的子类 AuthenticationForm
将由管理站点登录视图使用。
管理网站注销视图将使用的自定义模板的路径。
管理网站密码更改视图将使用的自定义模板的路径。
“管理网站密码更改完成”视图将使用的自定义模板的路径。
AdminSite
方法¶返回要放入管理网站中每个页面的模板上下文中的变量字典。
默认情况下包括以下变量和值:
site_header
: AdminSite.site_header
site_title
: AdminSite.site_title
site_url
: AdminSite.site_url
has_permission
: AdminSite.has_permission()
available_apps
:应用程序列表 application registry 可供当前用户使用。列表中的每个条目都是一个dict,用以下键表示应用程序:
app_label
:应用程序标签
app_url
:管理中应用程序索引的URL
has_module_perms
:一个布尔值,指示当前用户是否允许显示和访问模块的索引页。
models
:应用程序中可用的模型列表
每个模型都是一个具有以下键的dict:
model
:模范班
object_name
:模型的类名
name
:模型的复数名称
perms
答: dict
跟踪 add
, change
, delete
和 view
权限
admin_url
:模型的管理员变更列表URL
add_url
:用于添加新模型实例的管理URL
is_popup
:当前页面是否显示在弹出窗口中
is_nav_sidebar_enabled
: AdminSite.enable_nav_sidebar
log_entries
: AdminSite.get_log_entries()
方法返回应用程序列表。 application registry 可供当前用户使用。您可以选择将一个 app_label
参数以获取单个应用程序的详细信息。列表中的每个条目都是一个词典,表示具有以下关键字的应用程序:
app_label
:应用程序标签
app_url
:管理中应用程序索引的URL
has_module_perms
:一个布尔值,指示当前用户是否允许显示和访问模块的索引页。
models
:应用程序中可用的模型列表
name
:应用程序的名称
每个型号都是一本词典,其中包含以下关键字:
model
:模范班
object_name
:模型的类名
name
:模型的复数名称
perms
答: dict
跟踪 add
, change
, delete
和 view
权限
admin_url
:模型的管理员变更列表URL
add_url
:用于添加新模型实例的管理URL
应用程序和型号的列表按其名称的字母顺序排序。您可以重写此方法以更改管理索引页上的默认顺序。
返回 True
如果给定的用户 HttpRequest
有权限查看管理网站中的至少一个页面。默认为同时要求 User.is_active
和 User.is_staff
成为 True
.
用给定的 admin_class
. admin_class
默认为 ModelAdmin
(默认管理选项)。如果给出关键字参数——例如 list_display
--它们将作为管理类的选项应用。
加薪 ImproperlyConfigured
如果模型是抽象的。和 django.contrib.admin.exceptions.AlreadyRegistered
如果模型已注册。
取消注册给定的模型类(或类的可迭代类)。
加薪 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),
]
请注意,您可能不希望自动发现 admin
使用自己的模块时 AdminSite
实例,因为您可能会导入每个应用程序的所有 admin
你的模块 myproject.admin
模块。这意味着你需要 'django.contrib.admin.apps.SimpleAdminConfig'
而不是 'django.contrib.admin'
在你 INSTALLED_APPS
设置。
您可以覆盖默认值 django.contrib.admin.site
通过设置 default_site
自定义的属性 AppConfig
到 AdminSite
子类或返回站点实例的可调用项。
myproject/admin.py
¶from django.contrib import admin
class MyAdminSite(admin.AdminSite): ...
myproject/apps.py
¶from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = "myproject.admin.MyAdminSite"
myproject/settings.py
¶INSTALLED_APPS = [
# ...
"myproject.apps.MyAdminConfig", # replaces 'django.contrib.admin'
# ...
]
您可以在同一个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名称的前缀,用于 reversing them . 只有当您使用多个 AdminSite
.
就像 ModelAdmin
, AdminSite
提供了一个 get_urls()
可以重写以定义网站的其他视图的方法。要向管理网站添加新视图,请扩展基础 get_urls()
方法来包含新视图的模式。
备注
您呈现的任何使用管理模板或扩展基本管理模板的视图都应设置 request.current_app
在呈现模板之前。它应该设置为 self.name
如果您的视图位于 AdminSite
或 self.admin_site.name
如果您的视图位于 ModelAdmin
.
您可以通过在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/
并要求您将URL从 ^admin/
在包含管理应用程序本身的行之前)。
存在 admin_password_reset
命名的URL将导致“忘记密码?”链接显示在密码框下的默认管理员登录页上。
LogEntry
对象¶这个 LogEntry
类跟踪通过管理接口完成的对象的添加、更改和删除。
LogEntry
属性¶行动的日期和时间。
用户(AN) AUTH_USER_MODEL
实例)谁执行了操作。
这个 ContentType
修改对象的。
修改对象的主键的文本表示形式。
对象的 repr()
修改后。
记录的操作类型: ADDITION
, CHANGE
, DELETION
.
例如,要获取通过管理完成的所有添加的列表,请执行以下操作:
from django.contrib.admin.models import ADDITION, LogEntry
LogEntry.objects.filter(action_flag=ADDITION)
修改的详细说明。例如,在编辑的情况下,消息包含已编辑字段的列表。django管理站点将此内容格式化为JSON结构,以便 get_change_message()
无法重新编译以当前用户语言翻译的消息。不过,自定义代码可能会将其设置为普通字符串。建议您使用 get_change_message()
方法来检索此值,而不是直接访问它。
LogEntry
方法¶格式和翻译 change_message
转换为当前用户语言。在django 1.10之前创建的消息将始终以记录它们的语言显示。
当一个 AdminSite
已部署,该站点提供的视图可以使用django访问 URL reversing system .
这个 AdminSite
提供以下命名的URL模式:
页 |
URL名称 |
参数 |
---|---|---|
索引 |
|
|
登录 |
|
|
注销 |
|
|
密码更改 |
|
|
密码更改完成 |
|
|
I18N JavaScript |
|
|
应用程序索引页 |
|
|
重定向到对象的页面 |
|
|
各 ModelAdmin
实例提供了一组附加的命名URL:
页 |
URL名称 |
参数 |
---|---|---|
改变主义者 |
|
|
添加 |
|
|
历史 |
|
|
删除 |
|
|
变化 |
|
|
这个 UserAdmin
提供一个命名的URL:
页 |
URL名称 |
参数 |
---|---|---|
密码更改 |
|
|
这些命名的URL在应用程序命名空间中注册。 admin
以及与站点实例的名称相对应的实例命名空间。
因此-如果您想要获取对特定的更改视图的引用 Choice
对象(从Polls应用程序),您将在默认管理中调用:
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,))
这将找到管理应用程序的第一个已注册实例(无论实例名称如何),并解析为要更改的视图。 poll.Choice
该实例中的实例。
如果要在特定管理实例中查找URL,请将该实例的名称作为 current_app
对反向呼叫的提示。例如,如果您特别想要来自名为的管理实例的管理视图 custom
,您需要拨打:
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")
有关更多详细信息,请参阅 reversing namespaced URLs .
为了更容易地逆转模板中的管理URL,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
装饰器¶此装饰器可用于在可与 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
decorator¶此修饰符用于需要授权的管理视图。使用此函数装饰的视图将具有以下行为:
如果用户已登录,则是工作人员 (User.is_staff=True
,并且处于活动状态 (User.is_active=True
)正常执行视图。
否则,请求将被重定向到 login_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): ...
7月 22, 2024