Django管理站点

自动管理界面是Django最强大的部分之一。 它从您的模型中读取元数据,以提供一个快速,以模型为中心的界面,受信任的用户可以管理您网站上的内容。 管理员建议的使用仅限于组织的内部管理工具。 这不是为了构建你的整个前端。

管理员有很多定制的钩子,但要小心试图独占使用这些钩子。 如果您需要提供一个更加以流程为中心的接口来抽象出数据库表和字段的实现细节,那么可能是编写自己的视图的时候了。

在本文中,我们将讨论如何激活,使用和自定义Django的管理界面。

概述¶ T0>

管理员在startproject使用的默认项目模板中启用。

作为参考,这里是要求:

  1. 'django.contrib.admin'添加到INSTALLED_APPS设置中。
  2. The admin has four dependencies - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages and django.contrib.sessions. 如果这些应用程序不在您的INSTALLED_APPS列表中,请添加它们。
  3. Add django.contrib.auth.context_processors.auth and django.contrib.messages.context_processors.messages to the 'context_processors' option of the DjangoTemplates backend defined in your TEMPLATES as well as django.contrib.auth.middleware.AuthenticationMiddleware and django.contrib.messages.middleware.MessageMiddleware to MIDDLEWARE. 这些默认都是有效的,所以如果你手动调整了设置,你只需要这样做。
  4. 确定哪个应用程序的模型应该可以在管理界面进行编辑。
  5. For each of those models, optionally create a ModelAdmin class that encapsulates the customized admin functionality and options for that particular model.
  6. 实例化一个AdminSite并告诉它关于你的每个模型和ModelAdmin类。
  7. AdminSite实例挂钩到您的URLconf中。

完成这些步骤之后,您可以通过访问您挂钩的URL(默认情况下为/admin/)来使用您的Django管理站点。 如果您需要创建一个用户来登录,您可以使用createsuperuser命令。

其他主题

也可以看看

有关提供与生产中的管理员关联的静态文件(图像,JavaScript和CSS)的信息,请参阅Serving files

有问题吗? 试试FAQ: The admin

ModelAdmin objects

ModelAdmin[source]

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)

你需要一个ModelAdmin对象吗?

在前面的例子中,ModelAdmin类没有定义任何自定义值(还)。 因此,将提供默认的管理界面。 如果您对默认管理界面满意,则不需要定义ModelAdmin对象 - 您可以注册模型类而不提供ModelAdmin描述。 前面的例子可以简化为:

from django.contrib import admin
from myproject.myapp.models import Author

admin.site.register(Author)

register装饰器

register* modelssite = django.admin.sites.site[source] T5>

还有一个用于注册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, Reader, Editor
from myproject.admin_site import custom_admin_site

@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
    pass

You can’t use this decorator if you have to reference your model admin class in its __init__() method, e.g. super(PersonAdmin, self).__init__(*args, **kwargs). 你可以使用super().__ init __(* args, ** kwargs)

发现管理文件

当您在INSTALLED_APPS设置中放入'django.contrib.admin'时,Django自动在每个应用程序中查找admin模块并导入它。

应用。的AdminConfig T0> ¶ T1>

这是admin的默认AppConfig类。 它在Django启动时调用autodiscover()

应用。 SimpleAdminConfig T0> ¶ T1>

除了不调用autodiscover()之外,这个类像AdminConfig一样工作。

autodiscover()[source]

此功能会尝试在每个已安装的应用程序中导入admin模块。 预计这些模块将向管理员注册模型。

通常,当Django启动时,不需要像AdminConfig所调用的那样直接调用这个函数。

如果您使用的是自定义AdminSite,则通常会将所有ModelAdmin子类导入到您的代码中,并将其注册到自定义AdminSite 在这种情况下,为了禁用自动发现功能,您应该将'django.contrib.admin.apps.SimpleAdminConfig'而不是'django.contrib.admin'放入您的INSTALLED_APPS设置。

ModelAdmin options

ModelAdmin非常灵活。 它有几个选项来处理自定义界面。 所有选项都在ModelAdmin子类上定义:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    date_hierarchy = 'pub_date'
ModelAdmin.actions

在更改列表页面上提供的操作列表。 有关详细信息,请参阅Admin actions

的ModelAdmin。 actions_on_top T0> ¶ T1>
的ModelAdmin。 actions_on_bottom T0> ¶ T1>

控制操作栏在页面上的显示位置。 默认情况下,admin更改列表显示页面顶部的动作(actions_on_top = True; actions_on_bottom t4 > = False)。

的ModelAdmin。 actions_selection_counter T0> ¶ T1>

控制是否在操作下拉菜单旁边显示选择计数器。 默认情况下,管理员更改列表将显示它(actions_selection_counter = True)。

的ModelAdmin。 date_hierarchy T0> ¶ T1>

date_hierarchy设置为模型中的DateFieldDateTimeField的名称,更改列表页面将包含一个基于日期的向下钻取导航领域。

例:

date_hierarchy = 'pub_date'

您还可以使用__查找在相关模型中指定一个字段,例如:

date_hierarchy = 'author__pub_date'

这将基于可用数据智能地填充自身,例如,如果所有日期都在一个月内,则只会显示一天的深入分析。

在Django 1.11中更改:

添加了在相关模型上引用字段的功能。

注意

date_hierarchy uses QuerySet.datetimes() internally. 当启用时区支持(USE_TZ = True)时,请参阅其文档以了解一些注意事项。

的ModelAdmin。 empty_value_display T0> ¶ T1>

该属性将覆盖记录的空字段(None,空字符串等)的默认显示值。 默认值是-(破折号)。 例如:

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。排除 T0> ¶ T1>

这个属性,如果给出,应该是一个从表单中排除的字段名称列表。

例如,让我们考虑以下模型:

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)

如果您需要一个仅包含nametitle字段的Author模型的表单,则可以指定fieldsexclude

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    fields = ('name', 'title')

class AuthorAdmin(admin.ModelAdmin):
    exclude = ('birth_date',)

由于作者模型只有三个字段:nametitlebirth_date,所以上述声明产生的表单将包含完全相同的字段。

的ModelAdmin。字段 T0> ¶ T1>

使用fields选项对“添加”和“更改”页面上的表单进行简单的布局更改,例如仅显示可用字段的子集,修改其顺序或将其分组成行。 例如,您可以为django.contrib.flatpages.models.FlatPage模型定义一个更简单的管理员表单版本,如下所示:

class FlatPageAdmin(admin.ModelAdmin):
    fields = ('url', 'title', 'content')

在上面的例子中,只有字段urltitlecontent会依次显示在表单中。 fields可以包含ModelAdmin.readonly_fields中定义的值,以便显示为只读。

有关更复杂的布局需求,请参阅fieldsets选项。

list_display不同,fields选项可能只包含模型上的字段名称或由form指定的格式。 只有列在readonly_fields中时,才可能包含可卡因。

要在同一行显示多个字段,请将这些字段包装在自己的元组中。 在这个例子中,urltitle字段将显示在同一行上,content字段将显示在它们的下面:

class FlatPageAdmin(admin.ModelAdmin):
    fields = (('url', 'title'), 'content')

注意

这个fields选项不应该与fieldsets选项中的fields字典关键字混淆,如下一节所述。

如果fieldsfieldsets选项都不存在,则Django将默认显示不是AutoField的每个字段,并且editable=True,在单个字段集中,与字段在模型中定义的顺序相同。

的ModelAdmin。字段集 T0> ¶ T1>

设置fieldsets来控制管理员“添加”和“更改”页面的布局。

fieldsets是两元组的列表,其中每个二元组表示在管理员页面上的<fieldset> (A <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'),
        }),
    )

这导致了一个管理页面,如下所示:

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

如果fieldsetsfields选项都不存在,则Django将默认显示不是AutoField的每个字段,并且editable=True,在单个字段集中,与字段在模型中定义的顺序相同。

field_options字典可以具有以下键:

  • 领域

    要在此字段集中显示的字段名称的元组。 这个键是必需的。

    例:

    {
    '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中。

  • 包含额外CSS类以应用于字段集的列表或元组。

    例:

    {
    'classes': ('wide', 'extrapretty'),
    }
    

    由默认管理网站样式表定义的两个有用的类是collapsewide 带有collapse样式的字段集最初会在管理员中折叠,并替换为一个小的“点击展开”链接。 Fieldsets with the wide style will be given extra horizontal space.

  • 描述

    一组可选的额外文本,显示在每个字段集的顶部,在字段集的标题下。 由于其布局,该字符串不会呈现给TabularInline

    Note that this value is not HTML-escaped when it’s displayed in the admin interface. 这可以让你包括HTML如果你愿意。 或者,您可以使用纯文本和django.utils.html.escape()来转义任何HTML特殊字符。

的ModelAdmin。 filter_horizo​​ntal T0> ¶ T1>

By default, a ManyToManyField is displayed in the admin site with a <select multiple>. 但是,选择多个项目时,多选框可能很难使用。 添加一个ManyToManyField到这个列表将改为使用一个漂亮的不显眼的JavaScript“过滤器”接口,允许在选项中搜索。 未经选择和选定的选项并排显示在两个框中。 请参阅filter_vertical以使用垂直界面。

的ModelAdmin。 filter_vertical T0> ¶ T1>

filter_horizontal相同,但使用过滤器界面的垂直显示,在选定选项框上方显示未选定选项框。

的ModelAdmin。形式 T0> ¶ T1>

默认情况下,为您的模型动态创建一个ModelForm 它用于创建添加/更改页面上显示的表单。 您可以轻松地提供自己的ModelForm来覆盖添加/更改页面上的任何默认表单行为。 或者,可以使用ModelAdmin.get_form()方法自定义默认表单,而不是指定一个全新的表单。

有关示例,请参阅Adding custom validation to the admin部分。

注意

如果在ModelForm上定义Meta.model属性,则还必须定义Meta.fields属性(或Meta.exclude属性)。 但是,由于管理员有自己的定义字段的方式,所以Meta.fields属性将被忽略。

如果ModelForm仅用于管理员,则最简单的解决方案是省略Meta.model属性,因为ModelAdmin将提供使用正确的模型。 Alternatively, you can set fields = [] in the Meta class to satisfy the validation on the ModelForm.

注意

If your ModelForm and ModelAdmin both define an exclude option then ModelAdmin takes precedence:

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 T0> ¶ T1>

这提供了一种快捷方式来覆盖管理中使用的一些Field选项。 formfield_overrides is a dictionary mapping a field class to a dict of arguments to pass to the field at construction time.

由于这有点抽象,我们来看一个具体的例子。 formfield_overrides最常见的用途是为特定类型的字段添加自定义小部件。 所以,假设我们已经写了一个RichTextEditorWidget,我们想用它来代替默认的<textarea>的大文本字段。 以下是我们如何做到这一点:

from django.db import models
from django.contrib import admin

# Import our custom widget and our model from where they're defined
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': RichTextEditorWidget},
    }

请注意,字典中的键是实际的字段类,不是字符串。 价值是另一个字典;这些参数将传递给表单字段的__init__()方法。 有关详细信息,请参阅The Forms API

警告

If you want to use a custom widget with a relation field (i.e. ForeignKey or ManyToManyField), make sure you haven’t included that field’s name in raw_id_fields, radio_fields, or autocomplete_fields.

formfield_overrides不会让您在包含raw_id_fieldsradio_fieldsautocomplete_fields集的关系字段上更改窗口小部件。 这是因为raw_id_fieldsradio_fieldsautocomplete_fields意味着它们自己的自定义小部件。

的ModelAdmin。内联 T0> ¶ T1>

请参阅下面的InlineModelAdmin对象以及ModelAdmin.get_formsets_with_inlines()

的ModelAdmin。 list_display T0> ¶ T1>

设置list_display来控制在admin的更改列表页面上显示哪些字段。

例:

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'
    
  • 表示模型上的属性的字符串。 这与可调用的行为几乎相同,但是在这个上下文中的self是模型实例。 这是一个完整的示例:

    from django.db import models
    from django.contrib import admin
    
    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 fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. 如果你想这样做,给你的模型一个自定义的方法,并将该方法的名称添加到list_display (有关list_display中的自定义方法的更多信息,请参阅以下内容)

  • 如果该字段是一个BooleanFieldNullBooleanField,Django将显示一个相当的“on”或“off”图标,而不是TrueFalse

  • If the string given is a method of the model, ModelAdmin or a callable, Django will HTML-escape the output by default. 要避免用户输入并允许自己的非转义标签,请使用format_html()

    这是一个完整的示例模型:

    from django.db import models
    from django.contrib import admin
    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,一个空字符串,或者一个没有元素的迭代,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'
    
  • If the string given is a method of the model, ModelAdmin or a callable that returns True or False Django will display a pretty “on” or “off” icon if you give the method a boolean attribute whose value is True.

    这是一个完整的示例模型:

    from django.db import models
    from django.contrib import admin
    
    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.db import models
    from django.contrib import admin
    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')
    

    上面的方法会告诉Django在按照admin中的colored_first_name进行排序时通过first_name字段进行排序。

    要用admin_order_field指示降序,您可以在字段名称上使用连字符前缀。 使用上面的例子,这看起来像:

    colored_first_name.admin_order_field = '-first_name'
    

    admin_order_field supports query lookups to sort by values on related models. 此示例在列表显示中包含“作者名”列,并允许按名称对其进行排序:

    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的元素也可以是属性。 Please note however, that due to the way properties work in Python, setting short_description on a property is only possible when using the property() function and not with the @property decorator.

    例如:

    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',)
    
  • The field names in list_display will also appear as CSS classes in the HTML output, in the form of column-<field_name> on each <th> element. 例如,这可以用来设置CSS文件中的列宽。

  • Django将尝试按照以下顺序解释list_display的每个元素:

    • 模型的一个领域。
    • 一个可调用的。
    • 代表ModelAdmin属性的字符串。
    • 代表模型属性的字符串。

    例如,如果将first_name作为模型字段和ModelAdmin属性,则将使用模型字段。

使用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 T0> ¶ T1>

list_editable设置为允许在更改列表页面上编辑的模型上的字段名称列表。 也就是说,list_editable中列出的字段将作为表单窗口小部件显示在更改列表页面上,允许用户一次编辑和保存多行。

注意

list_editable interacts with a couple of other options in particular ways; you should note the following rules:

  • list_editable中的任何字段也必须位于list_display中。 您无法编辑未显示的字段!
  • 同一个字段不能列在list_editablelist_display_links中 - 一个字段不能是表单和链接。

如果这些规则中的任何一个被破坏,您将得到验证错误。

的ModelAdmin。 list_filter T0> ¶ T1>

设置list_filter激活管理员更改列表页右侧边栏中的过滤器,如下图所示:

../../../_images/list_filter.png

list_filter should be a list or tuple of elements, where each element should be of one of the following types:

  • a field name, where the specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey or ManyToManyField, for example:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = ('is_staff', 'company')
    

    list_filter中的字段名称也可以使用__查找来跨越关系,例如:

    class PersonAdmin(admin.UserAdmin):
        list_filter = ('company__name',)
    
  • 一个从django.contrib.admin.SimpleListFilter继承的类,您需要提供titleparameter_name属性并覆盖lookupsqueryset方法,例如:

    from datetime import date
    
    from django.contrib import admin
    from django.utils.translation import gettext_lazy as _
    
    class DecadeBornListFilter(admin.SimpleListFilter):
        # Human-readable title which will be displayed in the
        # right admin sidebar just above the filter options.
        title = _('decade born')
    
        # Parameter for the filter that will be used in the URL query.
        parameter_name = 'decade'
    
        def lookups(self, request, model_admin):
            """
            Returns a list of tuples. The first element in each
            tuple is the coded value for the option that will
            appear in the URL query. The second element is the
            human-readable name for the option that will appear
            in the right sidebar.
            """
            return (
                ('80s', _('in the eighties')),
                ('90s', _('in the nineties')),
            )
    
        def queryset(self, request, queryset):
            """
            Returns the filtered queryset based on the value
            provided in the query string and retrievable via
            `self.value()`.
            """
            # Compare the requested value (either '80s' or '90s')
            # to decide how to filter the queryset.
            if self.value() == '80s':
                return queryset.filter(birthday__gte=date(1980, 1, 1),
                                        birthday__lte=date(1989, 12, 31))
            if self.value() == '90s':
                return queryset.filter(birthday__gte=date(1990, 1, 1),
                                        birthday__lte=date(1999, 12, 31))
    
    class PersonAdmin(admin.ModelAdmin):
        list_filter = (DecadeBornListFilter,)
    

    注意

    为了方便,将HttpRequest对象传递给lookupsqueryset方法,例如:

    class AuthDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            if request.user.is_superuser:
                return super().lookups(request, model_admin)
    
        def queryset(self, request, queryset):
            if request.user.is_superuser:
                return super().queryset(request, queryset)
    

    Also as a convenience, the ModelAdmin object is passed to the lookups method, for example if you want to base the lookups on the available data:

    class AdvancedDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            """
            Only show the lookups if there actually is
            anyone born in the corresponding decades.
            """
            qs = model_admin.get_queryset(request)
            if qs.filter(birthday__gte=date(1980, 1, 1),
                          birthday__lte=date(1989, 12, 31)).exists():
                yield ('80s', _('in the eighties'))
            if qs.filter(birthday__gte=date(1990, 1, 1),
                          birthday__lte=date(1999, 12, 31)).exists():
                yield ('90s', _('in the nineties'))
    
  • 一个元组,其中第一个元素是一个字段名,第二个元素是一个从django.contrib.admin.FieldListFilter继承的类,例如:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = (
            ('is_staff', admin.BooleanFieldListFilter),
        )
    

    您可以使用RelatedOnlyFieldListFilter将相关模型的选择限制为该关系中涉及的对象:

    class BookAdmin(admin.ModelAdmin):
        list_filter = (
            ('author', admin.RelatedOnlyFieldListFilter),
        )
    

    Assuming author is a ForeignKey to a User model, this will limit the list_filter choices to the users who have written a book instead of listing all users.

    注意

    FieldListFilter API被认为是内部的,可能会改变。

列表过滤器通常只在过滤器有多个选项时出现。 过滤器的has_output()方法控制它是否出现。

可以指定用于呈现列表过滤器的自定义模板:

class FilterWithCustomTemplate(admin.SimpleListFilter):
    template = "custom_template.html"

有关具体示例,请参阅Django提供的默认模板(admin/filter.html)。

的ModelAdmin。 list_max_show_all T0> ¶ T1>

设置list_max_show_all来控制在“显示全部”管理更改列表页面上可以显示多少项目。 只有当结果总数小于或等于此设置时,管理员才会在更改列表中显示“全部显示”链接。 默认情况下,它被设置为200

的ModelAdmin。 list_per_page T0> ¶ T1>

设置list_per_page来控制每个分页的管理更改列表页面上显示的项目数量。 默认情况下,它被设置为100

设置list_select_related来告诉Django使用select_related()来检索admin更改列表页面上的对象列表。 这可以为您节省一堆数据库查询。

该值应该是布尔值,列表或元组。 默认是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()方法。

的ModelAdmin。排序 T0> ¶ T1>

设置ordering来指定如何在Django管理视图中排列对象列表。 这应该是与模型的ordering参数相同格式的列表或元组。

如果没有提供,Django管理员将使用模型的默认排序。

如果您需要指定动态顺序(例如,取决于用户或语言),则可以实现get_ordering()方法。

的ModelAdmin。分页程序 T0> ¶ T1>

paginator类用于分页。 默认情况下,使用django.core.paginator.Paginator 如果自定义paginator类与django.core.paginator.Paginator不具有相同的构造函数接口,则还需要为ModelAdmin.get_paginator()

的ModelAdmin。 prepopulated_fields T0> ¶ T1>

prepopulated_fields设置为字典映射字段名称到它应该预先填充的字段:

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

设置时,给定的字段将使用一些JavaScript来填充分配的字段。 此功能主要用于从一个或多个其他字段自动生成SlugField字段的值。 生成的值是通过连接源字段的值生成的,然后将该结果转换为有效的段落(例如用空格替换空格)。

字段预填充在添加表单上,而不是在更改表单上。 在创建一个对象之后,通常不希望发生slug改变(如果在其中使用了slug,会导致对象的URL改变)。

prepopulated_fields doesn’t accept DateTimeField, ForeignKey, OneToOneField, and ManyToManyField fields.

的ModelAdmin。 preserve_filters T0> ¶ T1>

管理员现在在创建,编辑或删除对象后,在列表视图中保留过滤器。 您可以通过将此属性设置为False来恢复以前的清除过滤器行为。

的ModelAdmin。 radio_fields T0> ¶ T1>

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey or have choices set. 如果一个字段存在于radio_fields中,Django将使用一个单选按钮接口。 假设groupPerson模型上的一个ForeignKey

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

您可以从django.contrib.admin模块中使用HORIZONTALVERTICAL

不要在radio_fields中包含字段,除非它是ForeignKey或者choices集合。

的ModelAdmin。 autocomplete_fields T0> ¶ T1>
Django 2.0新增功能

autocomplete_fields is a list of ForeignKey and/or ManyToManyField fields you would like to change to Select2 autocomplete inputs.

默认情况下,管理员为这些字段使用选择框接口(<select>)。 有时你不希望在下拉菜单中选择所有相关的实例。

Select2输入看起来与默认输入类似,但带有一个可异步加载选项的搜索功能。 如果相关模型具有多个实例,则这更快且更方便用户。

您必须在相关对象的ModelAdmin上定义search_fields,因为自动填充搜索使用它。

结果的排序和分页由相关的ModelAdminget_ordering()get_paginator()方法控制。

在以下示例中,ChoiceAdmin具有ForeignKeyQuestion的自动填充字段。 结果由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()实现是一个好主意。

You may also want to change the Paginator on very large tables as the default paginator always performs a count() query. 例如,您可以覆盖Paginator.count属性的默认实现。

的ModelAdmin。 raw_id_fields T0> ¶ T1>

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey. 有时你不想承担必须选择所有相关实例以显示在下拉菜单中的开销。

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 T0> ¶ T1>

默认情况下,管理员将所有字段显示为可编辑。 该选项中的任何字段(应该是listtuple)都将按原样显示其数据并且不可编辑;它们也被排除在用于创建和编辑的ModelForm之外。 请注意,当指定ModelAdmin.fieldsModelAdmin.fieldsets时,必须显示只读字段(否则将被忽略)。

如果使用readonly_fields,而没有通过ModelAdmin.fieldsModelAdmin.fieldsets定义显式排序,则会在所有可编辑字段之后最后添加它们。

A read-only field can not only display data from a model’s field, it can also display the output of a model’s method or a method of the ModelAdmin class itself. 这与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',)

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

    # short_description functions like a model field's verbose_name
    address_report.short_description = "Address"
的ModelAdmin。 save_as T0> ¶ T1>

设置save_as以在管理员更改表单上启用“另存为新功能”功能。

通常,对象有三个保存选项:“保存”,“保存并继续编辑”和“保存并添加另一个”。 如果save_asTrue,那么“保存并添加另一个”将被替换为“Save as new”按钮,用于创建一个新的对象现有的对象。

默认情况下,save_as设置为False

的ModelAdmin。 save_as_continue T0> ¶ T1>

save_as=True时,保存新对象后的默认重定向是该对象的更改视图。 如果设置了save_as_continue=False,则重定向将转到更改列表视图。

默认情况下,save_as_continue设置为True

的ModelAdmin。 save_on_top T0> ¶ T1>

设置save_on_top在管理员更改表单顶部添加保存按钮。

通常,保存按钮只出现在表单的底部。 如果您设置了save_on_top,则按钮将出现在顶部和底部。

默认情况下,save_on_top设置为False

的ModelAdmin。 search_fields T0> ¶ T1>

设置search_fields启用管理员更改列表页面上的搜索框。 这应该被设置为一个字段名称列表,只要有人在该文本框中提交了一个搜索查询就会被搜索到。

这些字段应该是某种文本字段,如CharFieldTextField 您也可以使用查找API“follow”表示法在ForeignKeyManyToManyField上执行相关查找:

search_fields = ['foreign_key__related_fieldname']

例如,如果您有作者的博客条目,则以下定义​​将启用通过作者的电子邮件地址搜索博客条目:

search_fields = ['user__email']

当有人在管理搜索框中进行搜索时,Django将搜索查询拆分为单词,并返回包含每个单词的所有对象,不区分大小写,其中每个单词必须至少位于search_fields For example, if search_fields is set to ['first_name', 'last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

对于更快速和/或更具限制性的搜索,请在运算符前加上字段名称:

^

使用“^”运算符来匹配字段开头处的开始。 For example, if search_fields is set to ['^first_name', '^last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')

这个查询比普通的'%john%'查询更有效率,因为数据库只需要检查列数据的开始,而不是查找整个列的数据。 另外,如果列上有一个索引,一些数据库可能能够使用该查询的索引,即使它是一个LIKE查询。

=

使用“=”运算符进行不区分大小写的精确匹配。 For example, if search_fields is set to ['=first_name', '=last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')

Note that the query input is split by spaces, so, following this example, it’s currently not possible to search for all records in which first_name is exactly 'john winston' (containing a space).

@
使用“@”运算符执行全文匹配。 这就像默认的搜索方法,但使用索引。 目前这只适用于MySQL。

如果您需要自定义搜索,则可以使用ModelAdmin.get_search_results()来提供额外的或替代的搜索行为。

的ModelAdmin。 show_full_result_count T0> ¶ T1>

Set show_full_result_count to control whether the full count of objects should be displayed on a filtered admin page (e.g. 99 results (103 total)). If this option is set to False, a text like 99 results (Show all) is displayed instead.

如果表中包含大量的行,那么show_full_result_count=True的缺省值将生成一个查询,以在表上执行完整的计数。

的ModelAdmin。 view_on_site T0> ¶ T1>

设置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

自定义模板选项

The Overriding admin templates section describes how to override or extend the default admin templates. 使用以下选项覆盖ModelAdmin视图使用的默认模板:

的ModelAdmin。 add_form_template T0> ¶ T1>

自定义模板的路径,由add_view()使用。

的ModelAdmin。 change_form_template T0> ¶ T1>

自定义模板的路径,由change_view()使用。

的ModelAdmin。 change_list_template T0> ¶ T1>

自定义模板的路径,由changelist_view()使用。

的ModelAdmin。 delete_confirmation_template T0> ¶ T1>

自定义模板的路径,由delete_view()用于在删除一个或多个对象时显示确认页面。

的ModelAdmin。 delete_selected_confirmation_template T0> ¶ T1>

自定义模板的路径,由delete_selected操作方法用于在删除一个或多个对象时显示确认页面。 请参阅actions documentation

的ModelAdmin。 object_history_template T0> ¶ T1>

自定义模板的路径,由history_view()使用。

的ModelAdmin。 popup_response_template T0> ¶ T1>
Django 1.11新增功能

自定义模板的路径,由response_add()response_change()response_delete()使用。

ModelAdmin methods

警告

When overriding ModelAdmin.save_model() and ModelAdmin.delete_model(), your code must save/delete the object. 它们不是用于否决的目的,而是允许你执行额外的操作。

的ModelAdmin。save_model(request, obj, form, change)[source]

The save_model method is given the HttpRequest, a model instance, a ModelForm instance, and a boolean value based on whether it is adding or changing the object. 重写此方法可以执行保存前或保存后的操作。 调用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_modelrequestobj[source]

delete_model方法提供了HttpRequest和一个模型实例。 重写此方法允许执行预处理或删除后操作。 调用super().delete_model()使用Model.delete()删除对象。

的ModelAdmin。save_formset(request, form, formset, change)[source]

The save_formset method is given the HttpRequest, the parent ModelForm instance and a boolean value based on whether it is adding or changing the parent object.

例如,要将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()

另见Saving objects in the formset中的对象。

的ModelAdmin。 get_ordering T0>(请求 T1>)¶ T2>

The get_ordering method takes a request as parameter and is expected to return a list or tuple for ordering similar to the ordering attribute. 例如:

class PersonAdmin(admin.ModelAdmin):

    def get_ordering(self, request):
        if request.user.is_superuser:
            return ['name', 'rank']
        else:
            return ['name']
的ModelAdmin。get_search_resultsrequestquerysetsearch_term[source] T6>

get_search_results方法将显示的对象列表修改为与所提供的搜索项匹配的对象列表。 它接受请求,应用当前过滤器的查询集以及用户提供的搜索术语。 它返回一个包含被修改来实现搜索的查询集的元组,以及一个指示结果是否包含重复项的布尔值。

默认实现将搜索ModelAdmin.search_fields中指定的字段。

此方法可能会被您自己的自定义搜索方法覆盖。 例如,您可能希望按整数字段进行搜索,或使用外部工具(如Solr或Haystack)。 您必须确定如果通过搜索方法实现的查询集更改可能会在结果中引入重复项,并在返回值的第二个元素中返回True

例如,要通过nameage进行搜索,可以使用:

class PersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'age')
    search_fields = ('name',)

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = 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, use_distinct

这个实现比search_fields = ('name', '= age') / t0>,例如,这会导致数字字段的字符串比较 ... 要么 UPPER( “polls_choice”。 “票” ::文) = UPPER( '4') 在PostgreSQL上。

The save_related method is given the HttpRequest, the parent ModelForm instance, the list of inline formsets and a boolean value based on whether the parent is being added or changed. 在这里,您可以为与父项相关的对象执行任何保存前或保存操作。 请注意,此时父对象及其形式已被保存。

的ModelAdmin。 get_autocomplete_fields T0>(请求 T1>)¶ T2>
Django 2.0新增功能

get_autocomplete_fields()方法被给予HttpRequest,并且期望返回字段名的listtuple将会像上面在ModelAdmin.autocomplete_fields部分中描述的那样用自动填充小部件显示。

的ModelAdmin。get_readonly_fieldsrequestobj = None

get_readonly_fields方法给出HttpRequestobj被编辑(或者None添加表单)预期会返回一个listtuple字段名称,这些字段名称将显示为只读,如上面在ModelAdmin.readonly_fields部分中所述。

的ModelAdmin。get_prepopulated_fieldsrequestobj = None

get_prepopulated_fields方法提供HttpRequestobj被编辑(或者None添加表单)预期会返回dictionary,如ModelAdmin.prepopulated_fields部分所述。

的ModelAdmin。get_list_display(request)[source]

get_list_display方法提供HttpRequest,并且期望返回字段名的listtuple显示在变更列表视图中,如ModelAdmin.list_display部分所述。

The get_list_display_links method is given the HttpRequest and the list or tuple returned by ModelAdmin.get_list_display(). 预期将返回变更列表中将被链接到变更视图的字段名称的NonelisttupleModelAdmin.list_display_links部分中。

的ModelAdmin。get_excluderequestobj = None
Django 1.11新增功能

The get_exclude method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of fields, as described in ModelAdmin.exclude.

的ModelAdmin。get_fields请求obj =无

The get_fields method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of fields, as described above in the ModelAdmin.fields section.

的ModelAdmin。get_fieldsetsrequestobj = None

The get_fieldsets method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page, as described above in the ModelAdmin.fieldsets section.

的ModelAdmin。get_list_filter(request)[source]

get_list_filter方法提供HttpRequest,并且期望返回与list_filter属性相同类型的序列类型。

get_list_select_related方法被赋予HttpRequest,并且应该返回一个布尔值或列表,如ModelAdmin.list_select_related所做的那样。

的ModelAdmin。get_search_fields(request)[source]

get_search_fields方法提供HttpRequest,并且期望返回与search_fields属性相同类型的序列类型。

的ModelAdmin。get_inline_instancesrequestobj = None[source]

The get_inline_instances method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list or tuple of InlineModelAdmin objects, as described below in the InlineModelAdmin section. 例如,以下内容将根据添加,更改和删除权限,在没有默认筛选的情况下返回内联:

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中定义的类的实例,或者在添加相关对象时可能会遇到“错误的请求”错误。

的ModelAdmin。get_urls()[source]

ModelAdmin上的get_urls方法以与URLconf相同的方式返回要用于该ModelAdmin的URL。 因此,您可以按照URL dispatcher中的说明扩展它们:

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.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 %}

注意

Notice that the custom patterns are included before the regular admin URLs: the admin URL patterns are very permissive and will match nearly anything, so you’ll usually want to prepend your custom URLs to the built-in ones.

在这个例子中,my_view将在/admin/myapp/mymodel/my_view/访问(假设管理网址包含在/admin/ 。)

但是,上面注册的self.my_view函数存在两个问题:

  • It will not perform any permission checks, so it will be accessible to the general public.
  • It will not provide any header details to prevent caching. 这意味着如果页面从数据库中检索数据,并且缓存中间件处于活动状态,页面可能会显示过时的信息。

由于这通常不是你想要的,Django提供了一个方便的包装来检查权限并将视图标记为不可缓存。 这个包装是ModelAdmin实例中的AdminSite.admin_view()(即self.admin_site.admin_view)。像这样使用它:

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

注意上面第五行的包装视图:

path('my_view/', self.admin_site.admin_view(self.my_view))

This wrapping will protect self.my_view from unauthorized access and will apply the django.views.decorators.cache.never_cache() decorator to make sure it is not cached if the cache middleware is active.

如果页面是可缓存的,但仍希望执行权限检查,则可以将cacheable=True参数传递给AdminSite.admin_view()

path('my_view/', self.admin_site.admin_view(self.my_view, cacheable=True))

ModelAdmin views have model_admin attributes. 其他AdminSite视图具有admin_site属性。

的ModelAdmin。get_formrequestobj = None** kwargs[source] ¶ T6>

返回一个用于管理添加和更改视图的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_inlinesrequestobj = None[source]

产量(FormSetInlineModelAdmin)对,用于管理添加和更改视图。

例如,如果您只想在更改视图中显示特定内联,则可以覆盖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 isinstance(inline, MyInline) and obj is None:
                continue
            yield inline.get_formset(request, obj), inline
的ModelAdmin。formfield_for_foreignkeydb_fieldrequest** 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实例拥有的汽车。

的ModelAdmin。formfield_for_manytomanydb_fieldrequest** 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_fielddb_field请求** 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'] += (('ready', 'Ready for deployment'),)
        return super().formfield_for_choice_field(db_field, request, **kwargs)

注意

在表单上设置的任何choices属性将仅限于表单域。 如果模型上的相应字段设置了选项,则提供给表单的选项必须是这些选项的有效子集,否则当保存模型本身之前进行验证时,表单提交将失败并带有ValidationError

的ModelAdmin。get_changelistrequest** kwargs[source]

返回用于列表的Changelist类。 默认情况下,使用django.contrib.admin.views.main.ChangeList 通过继承这个类,你可以改变列表的行为。

的ModelAdmin。get_changelist_formrequest** kwargs[source]

返回一个ModelForm类,用于更改列表页面上的Formset 要使用自定义表单,例如:

from django import forms

class MyForm(forms.ModelForm):
    pass

class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_form(self, request, **kwargs):
        return MyForm

注意

如果在ModelForm上定义Meta.model属性,则还必须定义Meta.fields属性(或Meta.exclude属性)。 However, ModelAdmin ignores this value, overriding it with the ModelAdmin.list_editable attribute. 最简单的解决方案是省略Meta.model属性,因为ModelAdmin将提供正确的模型以供使用。

的ModelAdmin。get_changelist_formsetrequest** kwargs[source]

如果使用list_editable,则返回ModelFormSet类用于更改列表页面。 要使用自定义的表单,例如:

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_formset(self, request, **kwargs):
        kwargs['formset'] = MyAdminFormSet
        return super().get_changelist_formset(request, **kwargs)
的ModelAdmin。lookup_allowed tt>(lookupvalue

更改列表页面中的对象可以使用来自URL的查询字符串的查找进行过滤。 例如,这就是list_filter的工作方式。 查找与QuerySet.filter()(例如,user__email=user@example.com)中使用的查找类似。 由于查询字符串中的查询可以由用户操作,因此必须对其进行消毒以防止未经授权的数据暴露。

The lookup_allowed() method is given a lookup path from the query string (e.g. 'user__email') and the corresponding value (e.g. 'user@example.com'), and returns a boolean indicating whether filtering the changelist’s QuerySet using the parameters is permitted. If lookup_allowed() returns False, DisallowedModelAdminLookup (subclass of SuspiciousOperation) is raised.

默认情况下,lookup_allowed()允许访问模型的本地字段,list_filter中使用的字段路径(但不是来自get_list_filter()以及limit_choices_toraw_id_fields中正确运行所需的查找。

重写此方法以自定义ModelAdmin子类允许的查找。

的ModelAdmin。 has_add_permission T0>(请求 T1>)¶ T2>

如果允许添加一个对象,则返回True,否则返回False

的ModelAdmin。has_change_permissionrequestobj = None

如果允许编辑obj,则返回True,否则返回False 如果obj为None,则应返回TrueFalse来指示是否允许编辑此类型的对象(例如False将被解释为意味着当前用户不被允许编辑这种类型的任何对象)。

的ModelAdmin。has_delete_permissionrequestobj = None

如果允许删除obj,则返回True,否则返回False 如果obj是None,则应返回TrueFalse以指示是否允许删除此类型的对象(例如,False将被解释为意味着当前用户不被允许删除这种类型的任何对象)。

的ModelAdmin。 has_module_permission T0>(请求 T1>)¶ T2>

如果在管理索引页面上显示模块并访问模块的索引页面,则应返回True,否则False 默认使用User.has_module_perms() Overriding it does not restrict access to the add, change or delete views, has_add_permission(), has_change_permission(), and has_delete_permission() should be used for that.

的ModelAdmin。 get_queryset T0>(请求 T1>)¶ T2>

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_userrequestmessagelevel = messages.INFOextra_tags ='' t4 >,fail_silently = False[source]

使用django.contrib.messages后端向用户发送消息。 请参阅custom ModelAdmin example

关键字参数允许您更改消息级别,添加额外的CSS标签,或者在未安装contrib.messages框架的情况下自动失败。 这些关键字参数与django.contrib.messages.add_message()匹配,请参阅该函数的文档以获取更多详细信息。 一个区别是,除了整数/常量之外,该级别还可以作为字符串标签传递。

的ModelAdmin。get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)[source]

返回用于此视图的分页程序实例。 默认情况下,实例化paginator的实例。

的ModelAdmin。response_addrequestobjpost_url_continue = None[source] ¶ T6>

确定add_view()阶段的HttpResponse

response_add is called after the admin form is submitted and just after the object and all the related instances have been created and saved. 您可以覆盖它来更改对象创建后的默认行为。

的ModelAdmin。response_changerequestobj[source]

确定change_view()阶段的HttpResponse

response_change is called after the admin form is submitted and just after the object and all the related instances have been saved. 您可以覆盖它以更改对象更改后的默认行为。

的ModelAdmin。response_deleterequestobj_displayobj_id[source] T6>

确定delete_view()阶段的HttpResponse

response_delete在对象被删除后被调用。 您可以覆盖它以更改删除对象后的默认行为。

obj_display is a string with the name of the deleted object.

obj_id is the serialized identifier used to retrieve the object to be deleted.

的ModelAdmin。get_changeform_initial_data(request)[source]

管理员更改表单上的初始数据的挂钩。 默认情况下,字段从GET参数中给出初始值。 For instance, ?name=initial_value will set the name field’s initial value to be initial_value.

这个方法应该在表单中返回一个字典 { '字段名': 'fieldval'}:

def get_changeform_initial_data(self, request):
    return {'name': 'custom_initial_value'}

其他方法

的ModelAdmin。add_view(request, form_url='', extra_context=None)[source]

Django视图为模型实例添加页面。 见下面的注释。

的ModelAdmin。change_view(request, object_id, form_url='', extra_context=None)[source]

用于模型实例编辑页面的Django视图。 见下面的注释。

的ModelAdmin。changelist_viewrequestextra_context = None[source]

用于模型实例的Django视图更改列表/操作页面。 见下面的注释。

的ModelAdmin。delete_viewrequestobject_idextra_context = None[source] ¶ T6>

Django查看模型实例删除确认页面。 见下面的注释。

的ModelAdmin。history_viewrequestobject_idextra_context = None[source] ¶ T6>

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 asset definitions

有时候你想添加一些CSS和/或JavaScript到添加/更改视图。 这可以通过在ModelAdmin上使用Media内部类来完成:

class ArticleAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ("my_styles.css",)
        }
        js = ("my_code.js",)

如果STATIC_URLNone),则staticfiles app会将STATIC_URL(或MEDIA_URL资产路径。 regular asset definitions on forms适用相同的规则。

jQuery的¶ T0>

Django管理JavaScript使用jQuery库。

为避免与用户提供的脚本或库冲突,Django的jQuery(版本2.2.3)命名空间为django.jQuery 如果您想在自己的管理JavaScript中使用jQuery而不包含第二个副本,则可以使用changelist上的django.jQuery对象并添加/编辑视图。

ModelAdmin类默认情况下需要jQuery,因此除非您有特定的需要,否则不需要将jQuery添加到您的ModelAdmin的媒体资源列表中。 例如,如果您需要将jQuery库放在全局名称空间中(例如使用第三方jQuery插件),或者需要更新版本的jQuery,则必须包含自己的副本。

Django provides both uncompressed and ‘minified’ versions of jQuery, as jquery.js and jquery.min.js respectively.

ModelAdmin and InlineModelAdmin have a media property that returns a list of Media objects which store paths to the JavaScript files for the forms and/or formsets. 如果DEBUGTrue,它将返回各种JavaScript文件的未压缩版本,包括jquery.js;如果不是,它将返回“缩小”版本。

将自定义验证添加到admin

在管理中添加自定义的数据验证非常简单。 自动管理界面重复使用django.formsModelAdmin类为您提供定义自己的窗体的能力:

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

MyArticleAdminForm can be defined anywhere as long as you import where needed. 现在在您的表单中,您可以为任何字段添加您自己的自定义验证:

class MyArticleAdminForm(forms.ModelForm):
    def clean_name(self):
        # do something that validates your data
        return self.cleaned_data["name"]

在这里使用ModelForm非常重要,否则可能会破坏。 有关更多信息,请参阅custom validation上的forms文档,更具体地说,model form validation notes

InlineModelAdmin对象

InlineModelAdmin T0> ¶ T1>
TabularInline[source]
StackedInline[source]

管理界面可以在同一页面上作为父模型编辑模型。 这些被称为内联。 假设你有这两个模型:

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 shares many of the same features as ModelAdmin, and adds some of its own (the shared features are actually defined in the BaseModelAdmin superclass). 共享功能是:

InlineModelAdmin类添加:

InlineModelAdmin。模型 T0> ¶ T1>

内联使用的模型。 这是必需的。

InlineModelAdmin。 FK_NAME T0> ¶ T1>

模型上外键的名称。 In most cases this will be dealt with automatically, but fk_name must be specified explicitly if there are more than one foreign key to the same parent model.

InlineModelAdmin。表单集 T0> ¶ T1>

默认为BaseInlineFormSet 使用你自己的formset可以给你很多定制的可能性。 内联是围绕model formsets构建的。

InlineModelAdmin。形式 T0> ¶ T1>

form的值默认为ModelForm 这是为内联创建formset时传递给inlineformset_factory()的内容。

警告

在为InlineModelAdmin表单编写自定义验证时,谨慎编写依赖于父模型的特性的验证。 如果父模型无法验证,则可能会保留在Validation on a ModelForm中的警告中所述的不一致状态。

InlineModelAdmin。类 T0> ¶ T1>

包含额外CSS类的列表或元组,用于应用于为内联呈现的字段集。 默认为None 与在fieldsets中配置的类一样,内联collapse类将首先折叠,并且其标题将具有一个小的“显示”链接。

InlineModelAdmin。额外 T0> ¶ T1>

这将控制除了初始表单之外,formset将显示的额外表单的数量。 有关更多信息,请参阅formsets documentation

对于启用了JavaScript的浏览器的用户,除了作为extra参数提供的内容之外,还提供了一个“添加另一个”链接,以允许添加任意数量的附加内联。

如果当前显示的表格数量超过了max_num,或者用户没有启用JavaScript,动态链接将不会显示。

InlineModelAdmin.get_extra() also allows you to customize the number of extra forms.

InlineModelAdmin。 MAX_NUM T0> ¶ T1>

这将控制内联中显示的最大表单数量。 这并不直接关联对象的数量,但如果值足够小,则可以。 有关更多信息,请参阅Limiting the number of editable objects

InlineModelAdmin.get_max_num() also allows you to customize the maximum number of extra forms.

InlineModelAdmin。 MIN_NUM T0> ¶ T1>

这将控制内联中显示的最少数量的表单。 有关更多信息,请参阅modelformset_factory()

InlineModelAdmin.get_min_num() also allows you to customize the minimum number of displayed forms.

InlineModelAdmin。 raw_id_fields T0> ¶ T1>

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey. 有时你不想承担必须选择所有相关实例以显示在下拉菜单中的开销。

raw_id_fields是您想要更改为ForeignKeyManyToManyFieldInput小部件的字段列表:

class BookInline(admin.TabularInline):
    model = Book
    raw_id_fields = ("pages",)
InlineModelAdmin。模板 T0> ¶ T1>

用于在页面上呈现内联的模板。

InlineModelAdmin。 verbose_name T0> ¶ T1>

覆盖模型的内部Meta类中的verbose_name

InlineModelAdmin。 verbose_name_plural T0> ¶ T1>

覆盖模型的内部Meta类中的verbose_name_plural

InlineModelAdmin。 can_delete T0> ¶ T1>

指定是否可以在行内删除嵌入式对象。 默认为True

指定是否可以在admin中更改的内联对象链接到更改表单。 默认为False

InlineModelAdmin。get_formsetrequestobj = None** kwargs

返回一个BaseInlineFormSet类用于管理添加/更改视图。 请参阅ModelAdmin.get_formsets_with_inlines的示例。

InlineModelAdmin。get_extrarequestobj = 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_numrequestobj = 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_numrequestobj = None** kwargs

返回要使用的内联表单的最小数量。 默认情况下,返回InlineModelAdmin.min_num属性。

重写此方法以编程方式确定内联表单的最小数量。 例如,这可能基于模型实例(作为关键字参数obj传递)。

使用具有两个或更多外键的模型来处理同一个父模型

有时可能有多个外键到同一个模型。 以这个模型为例:

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 &lt; select 多个&gt; t4>,水平或垂直过滤器或raw_id_admin小部件。 但是,也可以用内联替换这些小部件。

假设我们有以下模型:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, related_name='groups')

如果要使用内联显示多对多关系,可以通过为关系定义一个InlineModelAdmin对象来实现:

from django.contrib import admin

class MembershipInline(admin.TabularInline):
    model = Group.members.through

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

class GroupAdmin(admin.ModelAdmin):
    inlines = [
        MembershipInline,
    ]
    exclude = ('members',)

在这个例子中有两个值得注意的特性。

首先 - MembershipInline类引用Group.members.through through属性是对管理多对多关系的模型的引用。 当你定义一个多对多的字段时,这个模型是由Django自动创建的。

其次,GroupAdmin必须手动排除members字段。 Django在定义关系的模型(在这种情况下,Group)上显示一个多对多字段的管理小部件。 如果你想使用内联模型来表示多对多的关系,你必须告诉Django的管理员不要显示这个小部件 - 否则你将最终在管理页面上有两个小部件来管理关系。

请注意,使用此技术时,不会触发m2m_changed信号。 这是因为就管理员而言,through只是一个有两个外键字段而不是多对多关系的模型。

In all other respects, the InlineModelAdmin is exactly the same as any other. 您可以使用任何正常的ModelAdmin属性自定义外观。

使用多对多的中介模型

当您使用ManyToManyFieldthrough参数指定中介模型时,admin默认情况下不会显示小部件。 这是因为该中介模型的每个实例需要比可以在单个小部件中显示更多的信息,并且多个小部件所需的布局将根据中间模型而变化。

但是,我们仍然希望能够内嵌编辑这些信息。 幸运的是,内联管理员模型很容易实现。 假设我们有以下模型:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

在admin中显示这个中间模型的第一步是为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,)

最后,用admin站点注册您的PersonGroup模型:

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

现在,您的管理网站已设置为从PersonGroup详细信息页面内联编辑Membership对象。

使用泛型关系作为内联

可以使用内联的一般相关的对象。 假设您有以下型号:

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey

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)

If you want to allow editing and creating an Image instance on the Product, add/change views you can use GenericTabularInline or GenericStackedInline (both subclasses of GenericInlineModelAdmin) provided by admin. 它们分别为代表内联对象的表单实现表格和堆叠的可视布局,就像它们的非通用对象一样。 他们的行为就像其他任何内联。 在本示例应用程序的admin.py中:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

class ProductAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

admin.site.register(Product, ProductAdmin)

有关更多具体信息,请参阅contenttypes documentation

覆盖管理模板

重写管理模块用于生成管理站点各种页面的许多模板相对比较容易。 您甚至可以为特定的应用程序或特定的模型覆盖这些模板中的一部分。

设置您的项目管理模板目录

管理员模板文件位于contrib/admin/templates/admin目录中。

为了覆盖其中的一个或多个,请首先在您的项目的templates目录中创建一个admin目录。 这可以是您在TEMPLATES设置中的DjangoTemplates后端的DIRS选项中指定的任何目录。 If you have customized the 'loaders' option, be sure 'django.template.loaders.filesystem.Loader' appears before 'django.template.loaders.app_directories.Loader' so that your custom templates will be found by the template loading system before those that are included with django.contrib.admin.

admin目录中,创建以应用程序命名的子目录。 在这些应用程序子目录中创建以您的模型命名的子目录。 请注意,当查找目录时,管理应用程序将小写模型名称,因此,如果要在区分大小写的文件系统上运行应用程序,请确保以全部小写命名目录。

要覆盖特定应用程序的管理员模板,请从django/contrib/admin/templates/admin目录复制并编辑该模板,并将其保存到您刚刚创建的其中一个目录中。

For example, if we wanted to add a tool to the change list view for all the models in an app named my_app, we would copy contrib/admin/templates/admin/change_list.html to the templates/admin/my_app/ directory of our project, and make any necessary changes.

如果我们只想为名为“Page”的特定模型添加一个工具到更改列表视图,我们会将同一个文件复制到我们项目的templates/admin/my_app/page目录下。

重写与替换管理模板

由于管理模板的模块化设计,替换整个模板通常既不必要也不可取。 只覆盖模板中需要更改的部分几乎总是更好。

为了继续上面的例子,我们要为Page模型的History工具旁边添加一个新的链接。 查看change_form.html后,我们确定只需要覆盖object-tools-items块。 因此,这里是我们新的change_form.html

{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
    <li>
        <a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% trans "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">{% trans "View on site" %}</a>
        </li>
    {% endif %}
{% endblock %}

而就是这样! 如果我们把这个文件放在templates/admin/my_app目录中,我们的链接将出现在my_app中所有模型的变化表单上。

每个应用或模型可覆盖的模板

并非每个应用或每个模型都可以覆盖contrib/admin/templates/admin中的所有模板。 以下可以:

  • app_index.html
  • change_form.html
  • change_list.html
  • delete_confirmation.html
  • object_history.html
  • popup_response.html
在Django 1.11中更改:

添加了覆盖popup_response.html模板的功能。

对于那些不能以这种方式覆盖的模板,您仍然可以覆盖整个项目的模板。 只需将新版本放在templates/admin目录中即可。 这对创建自定义404和500页面特别有用。

注意

某些管理模板(如change_list_results.html)用于呈现自定义包含标记。 这些可能会被覆盖,但在这种情况下,您可能最好创建自己的标签版本,并给它一个不同的名称。 这样你可以有选择地使用它。

根和登录模板

如果您想更改索引,登录或注销模板,最好创建自己的AdminSite实例(参见下文),并更改AdminSite.index_templateAdminSite.login_templateAdminSite.logout_template属性。

AdminSite对象

AdminSite(name='admin')[source]

Django管理站点由django.contrib.admin.sites.AdminSite实例表示。默认情况下,该类的一个实例被创建为django.contrib.admin.site,您可以使用它注册模型和ModelAdmin实例。

构建AdminSite的实例时,可以使用name参数为构造函数提供唯一的实例名称。 此实例名称用于标识实例,特别是在reversing admin URLs时。 如果未提供实例名称,将使用默认实例名称admin 有关自定义AdminSite类的示例,请参阅Customizing the AdminSite class

AdminSite属性

模板可以覆盖或扩展基本管理模板,如Overriding admin templates中所述。

AdminSite。 site_header T0> ¶ T1>

放在每个管理页面顶部的文本,如<h1>(一个字符串)。 默认情况下,这是“Django管理”。

AdminSite。 SITE_TITLE T0> ¶ T1>

放在每个管理页面<title>(字符串)末尾的文本。 默认情况下,这是“Django网站管理员”。

AdminSite。 SITE_URL T0> ¶ T1>

每个管理页面顶部的“查看网站”链接的网址。 默认情况下,site_url/ 将其设置为None删除链接。

对于在子路径上运行的站点,each_context()方法检查当前请求是否有request.META['SCRIPT_NAME']设置并使用该值,如果site_url未设置为/以外的其他内容。

AdminSite。 index_title T0> ¶ T1>

放在管理索引页面顶部的文本(一个字符串)。 默认情况下,这是“网站管理”。

AdminSite。 index_template T0> ¶ T1>

管理网站主要索引视图将使用的自定义模板的路径。

AdminSite。 app_index_template T0> ¶ T1>

管理网站应用程序索引视图将使用的自定义模板的路径。

AdminSite。 empty_value_display T0> ¶ T1>

用于在管理站点的更改列表中显示空值的字符串。 默认为短划线。 通过在字段中设置empty_value_display属性,也可以在ModelAdmin基础上和ModelAdmin中的自定义字段上覆盖该值。 示例请参阅ModelAdmin.empty_value_display

AdminSite。 login_template T0> ¶ T1>

管理网站登录视图将使用自定义模板的路径。

AdminSite。 login_form T0> ¶ T1>

管理网站登录视图将使用AuthenticationForm的子类。

AdminSite。 logout_template T0> ¶ T1>

管理网站注销视图将使用的自定义模板的路径。

AdminSite。 password_change_template T0> ¶ T1>

管理站点密码更改视图将使用的自定义模板的路径。

AdminSite。 password_change_done_template T0> ¶ T1>

将由管理员站点密码更改完成视图使用的自定义模板的路径。

AdminSite方法

AdminSite。each_context(request)[source]

返回管理站点中每个页面的模板上下文中的变量字典。

包括以下变量和默认值:

  • site_headerAdminSite.site_header

  • site_titleAdminSite.site_title

  • site_urlAdminSite.site_url

  • has_permissionAdminSite.has_permission()

  • available_apps:可用于当前用户的application registry中的应用程序列表。 列表中的每个条目都是一个代表具有以下键的应用程序的词典:

    • app_label:应用程序标签
    • app_url: the URL of the application index in the admin
    • has_module_perms:布尔值,指示是否允许当前用户显示和访问模块的索引页
    • models:应用程序中可用模型的列表

    每个模型是一个字典与以下键:

    • object_name:模型的类名称
    • name:模型的复数名称
    • perms:a dict跟踪addchangedelete权限
    • admin_url: admin changelist URL for the model
    • add_url:管理员URL添加一个新的模型实例
AdminSite。has_permission(request)[source]

如果给定HttpRequest的用户有权查看管理站点中的至少一个页面,则返回True 默认要求User.is_activeUser.is_staffTrue

AdminSite。registermodel_or_iterableadmin_class = None** options[source] ¶ T6>

使用给定的admin_class注册给定的模型类(或类的迭代)。 admin_class默认为ModelAdmin(默认管理选项)。 如果给出关键字参数 - 例如list_display - 它们将作为选项应用于管理员类。

如果模型是抽象的,则引发ImproperlyConfigured django.contrib.admin.sites.AlreadyRegistered如果模型已经注册。

AdminSite实例连接到你的URLconf

设置Django管理员的最后一步是将您的AdminSite实例挂接到您的URLconf中。 通过在AdminSite.urls方法中指定给定的URL来执行此操作。 没有必要使用include()

在这个例子中,我们在URL /admin/上注册默认的AdminSite实例django.contrib.admin.site

# 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.admin import AdminSite

from .models import MyModel

class MyAdminSite(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模块,因为您可能会导入所有每个应用admin模块在您的myproject.admin模块中。 这意味着您需要在INSTALLED_APPS中放入'django.contrib.admin.apps.SimpleAdminConfig',而不是'django.contrib.admin'设置。

多个管理站点在同一个URLconf

在同一个Django驱动的网站上创建管理站点的多个实例是很容易的。 只需创建AdminSite的多个实例,并将每个实例根目录另一个URL。

In this example, the URLs /basic-admin/ and /advanced-admin/ feature separate versions of the admin site – using the AdminSite instances myproject.admin.basic_site and myproject.admin.advanced_site, respectively:

# urls.py
from django.urls import path
from myproject.admin import basic_site, advanced_site

urlpatterns = [
    path('basic-admin/', basic_site.urls),
    path('advanced-admin/', advanced_site.urls),
]

AdminSite instances take a single argument to their constructor, their name, which can be anything you like. 这个参数成为reversing them 这只在您使用多个AdminSite时才有必要。

添加视图到管理网站

就像ModelAdmin一样,AdminSite提供了一个get_urls()方法,可以覆盖该方法来定义站点的附加视图。 要将新视图添加到管理站点,请扩展基础get_urls()方法以包含新视图的模式。

注意

您呈现的任何使用管理模板的视图,或扩展基本管理模板,都应在呈现模板之前设置request.current_app It should be set to either self.name if your view is on an AdminSite or self.admin_site.name if your view is on a ModelAdmin.

添加密码重置功能

您可以通过在您的URLconf中添加几行来为管理网站添加密码重置功能。 具体来说,添加这四种模式:

from django.contrib.auth import views as auth_views

path(
    'admin/password_reset/',
    auth_views.PasswordResetView.as_view(),
    name='admin_password_reset',
),
path(
    'admin/password_reset/done/',
    auth_views.PasswordResetDoneView.as_view(),
    name='password_reset_done',
),
path(
    'reset/<uidb64>/<token>/',
    auth_views.PasswordResetConfirmView.as_view(),
    name='password_reset_confirm',
),
path(
    'reset/done/',
    auth_views.PasswordResetCompleteView.as_view(),
    name='password_reset_complete',
),

(假设你已经在admin/添加了管理员,并要求你在包含管理应用程序本身的行之前放置以^admin/开头的URL)。

如果存在admin_password_reset命名的URL,会导致“忘记密码?”链接出现在密码框的默认管理员登录页面上。

LogEntry对象

楷模。 LogEntry T0> ¶ T1>

The LogEntry class tracks additions, changes, and deletions of objects done through the admin interface.

LogEntry属性

LogEntry。 ACTION_TIME T0> ¶ T1>

行动的日期和时间。

LogEntry。用户 T0> ¶ T1>

执行操作的用户(一个AUTH_USER_MODEL实例)。

LogEntry。 CONTENT_TYPE T0> ¶ T1>

修改后的对象的ContentType

LogEntry。的object_id T0> ¶ T1>

修改对象的主键的文本表示。

LogEntry。 object_repr T0> ¶ T1>

修改后的对象`s repr()

LogEntry。 action_flag T0> ¶ T1>

记录的操作类型:ADDITIONCHANGEDELETION

例如,要获取通过管理员完成的所有添加的列表:

from django.contrib.admin.models import LogEntry, ADDITION

LogEntry.objects.filter(action_flag=ADDITION)
LogEntry。 change_message的 T0> ¶ T1>

修改的详细说明。 例如,在编辑的情况下,消息包含编辑字段的列表。 Django管理站点将此内容格式化为JSON结构,以便get_change_message()可以重新构造用当前用户语言翻译的消息。 自定义代码可能会将其设置为纯字符串。 建议您使用get_change_message()方法来检索此值,而不是直接访问它。

LogEntry方法

LogEntry。 get_edited_object T0>()¶ T1>

返回引用对象的快捷方式。

LogEntry。 get_change_message T0>()¶ T1>

格式化并将change_message翻译成当前的用户语言。 在Django 1.10之前创建的消息将始终以它们被记录的语言显示。

反转管理员网址

当部署AdminSite时,可以使用Django的URL reversing system访问该站点提供的视图。

AdminSite提供以下指定的网址格式:

网址名称 参数
指数 指数  
登录 登录  
登出 登出  
密码更改 password_change  
密码更改完成 password_change_done  
i18n JavaScript jsi18n  
应用程序索引页 app_list app_label
重定向到对象的页面 view_on_site content_type_idobject_id

每个ModelAdmin实例都提供了一组额外的指定URL:

网址名称 参数
更改列表 {{ 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提供了一个指定的URL:

网址名称 参数
密码更改 auth_user_password_change 用户名

这些命名的URL在应用程序名称空间admin中注册,并且与实例名称空间相对应,该名称空间与Site实例的名称相对应。

因此,如果您想要在默认管理员中获取特定Choice对象(来自民意调查应用程序)的“更改”视图的引用,您可以调用:

>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,))

这将找到管理应用程序的第一个注册实例(不管实例名称如何),并解析到该实例中用于更改poll.Choice实例的视图。

如果要在特定的管理实例中查找URL,请将该实例的名称作为current_app提示提供给反向调用。 例如,如果您特别需要来自名为custom的管理实例的管理视图,则需要调用:

>>> change_url = reverse('admin:polls_choice_change', args=(c.id,), current_app='custom')

有关更多详细信息,请参阅reversing namespaced URLs的文档。

为了让模板中的管理url更容易反转,Django提供了一个以action作为参数的admin_urlname过滤器:

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

以上示例中的操作与上述ModelAdmin实例的URL名称的最后一部分相匹配。 opts变量​​可以是任何具有app_labelmodel_name属性的对象,通常由当前模型的管理视图提供。

staff_member_required装饰器

staff_member_requiredredirect_field_name ='next'login_url ='admin:login'[source] ¶ T5>

这个装饰器用于需要授权的管理视图。 用这个函数装饰的视图将具有以下行为:

  • 如果用户已经登录,是职员(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):
    ...