Django - 管理站点

  • Django 最强大的部分之一是自动管理界面。它从你的模型中读取元数据,提供一个快速的、以模型为中心的界面,受信任的用户可以管理你网站上的内容。管理的推荐使用范围仅限于一个组织的内部管理工具。它不打算用于围绕你的整个前端构建。
  • 管理有很多用于定制的钩子,但要注意不要试图专门使用这些钩子。如果你需要提供一个更以流程为中心的接口,抽象掉数据库表和字段的实现细节,那么可能是时候编写自己的视图了。
  • 在本文档中,我们将讨论如何激活、使用和定制 Django 的管理界面。
  • 使用以下命令创建管理员用户

    1
    python .\manage.py createsuperuser
  • 输入该命令后按照提示的顺序依次输入 用户名邮箱密码确认密码 即可,例如:

    1
    2
    3
    4
    5
    用户名: admin
    电子邮件地址: admin@163.com
    Password:
    Password (again):
    Superuser created successfully.
  • 注意和说明

    • 如果需要创建一个用户来登录,请使用 createsuperuser 命令。默认情况下,登录管理需要用户的 is_staff 属性设置为 True
    • 只有安装了 Django 的 认证系统django.contrib.auth),这个命令才有效。
    • 当交互式运行时,该命令将提示为新的超级用户账户提供密码。非交互式运行时,可以通过设置 DJANGO_SUPERUSER_PASSWORD 环境变量提供密码。否则,将不设置密码,超级用户账户将无法登录,直到手动为其设置密码。
    • 在非交互模式下, USERNAME_FIELD 和必填字段(列在 REQUIRED_FIELDS 中)回落到 DJANGO_SUPERUSER_<uppercase_field_name> 环境变量,除非它们被命令行参数覆盖。例如,要提供一个 email 字段,你可以使用 DJANGO_SUPERUSER_EMAIL 环境变量。

登录

  • 在你采取了这些步骤之后,你就可以通过访问你挂接的 URL(默认是 /admin/)来使用管理站点。如:

    1
    http://127.0.0.1:8000/admin/

    注意:登录之前需要先启动 Django 服务

  • 登录的时候需要输入刚才设置的 用户名密码

  • ModelAdmin 类是管理界面中模型的表示。通常,这些都存储在你的应用程序中一个名为 admin.py 的文件中。让我们来看看 ModelAdmin 的一个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from django.contrib import admin

    from user.models import User


    # Register your models here.
    class UserAdmin(admin.ModelAdmin):
    pass


    admin.site.register(User)
  • 在前面的例子中,ModelAdmin 类没有定义任何自定义值(还没有)。因此,将提供默认的管理界面。如果你对默认的管理界面满意,你根本不需要定义一个 ModelAdmin 对象 —— 你可以不提供 ModelAdmin 描述而注册模型类。前面的例子可以简化为:

    1
    2
    3
    4
    5
    6
    from django.contrib import admin

    from user.models import User

    # Register your models here.
    admin.site.register(User)
  • 还有一个装饰器用于注册你的 ModelAdmin 类:

    1
    2
    3
    4
    5
    6
    from django.contrib import admin
    from .models import Author

    @admin.register(Author)
    class AuthorAdmin(admin.ModelAdmin):
    pass
  • 它接受一个或多个模型类,让它在 ModelAdmin 注册。如果你使用的是自定义的 AdminSite,请使用 site 关键字参数传递它:

    1
    2
    3
    4
    5
    6
    7
    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)

  • 简介

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.contrib import admin

    from user.models import User


    # Register your models here.
    class UserAdmin(admin.ModelAdmin):
    # 设置 list_display 来控制哪些字段显示在管理的变更列表页面
    list_display = ('username', 'phone', 'first_name', 'last_name', 'date_joined')


    admin.site.register(User, UserAdmin)
  • actions

    要在变更列表页上提供的动作列表。详见 管理动作

  • actions_on_topactions_on_bottom

    控制动作栏在页面的哪个位置出现。默认情况下,管理员更改列表在页面顶部显示动作(actions_on_top = True; actions_on_bottom = False)。

  • actions_selection_counter

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

  • date_hierarchy

    • date_hierarchy 设置为你的模型中 DateFieldDateTimeField 的名称,变化列表页将包括一个基于日期的向下扩展。
    • 举例:
      1
      date_hierarchy = 'pub_date'
    • 你也可以使用 __ 查找来指定相关模型上的字段,例如:
      1
      date_hierarchy = 'author__pub_date'
    • 这将根据可用的数据智能地填充自己,例如,如果所有的日期都在一个月内,它将只显示日级的向下扩展。
    • 备注:
      date_hierarchy 内部使用 QuerySet.datetimes()。当启用时区支持时,请参考它的文档中的一些注意事项(USE_TZ = True)。
  • empty_value_display

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

      1
      2
      3
      4
      from django.contrib import admin

      class AuthorAdmin(admin.ModelAdmin):
      empty_value_display = '-empty-'
    • 你也可以用 AdminSite.empty_value_display 覆盖所有管理页面的 empty_value_display,或者像这样覆盖特定字段:

      1
      2
      3
      4
      5
      6
      7
      8
      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
  • exclude

    • 如果给定了这个属性,那么这个属性应该是一个要从表单中排除的字段名列表。
    • 例如,我们考虑以下模型:
      1
      2
      3
      4
      5
      6
      from django.db import models

      class Author(models.Model):
      name = models.CharField(max_length=100)
      title = models.CharField(max_length=3)
      birth_date = models.DateField(blank=True, null=True)
    • 如果你想让 Author 模型的表格只包括 nametitle 字段,你可以指定 fieldsexclude ,如:
      1
      2
      3
      4
      5
      6
      7
      from django.contrib import admin

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

      class AuthorAdmin(admin.ModelAdmin):
      exclude = ('birth_date',)
    • 由于 Author 模型只有三个字段,即 nametitlebirth_date,因此上述声明所产生的表单将包含完全相同的字段。
  • fields

    • 使用 fields 选项在 “添加” 和 “更改” 页面的表单中进行简单的布局修改,比如只显示可用字段的子集,修改它们的顺序,或者将它们分成几行。例如,你可以为 django.contrib.flatpages.models.FlatPage 模型定义一个更简单的管理表单版本,如下所示:
      1
      2
      class FlatPageAdmin(admin.ModelAdmin):
      fields = ('url', 'title', 'content')
    • 在上面的例子中,只有 urltitlecontent 等字段会依次显示。fields 可以包含 ModelAdmin.readonly_fields 中定义的值,以只读方式显示。
    • 对于更复杂的布局需求,请参阅 fieldets 选项。
    • fields 选项接受与 list_display 相同类型的值,只是不接受作为可调用对象的值。模型和模型管理方法的名称只有在 readonly_fields 中列出时才会被使用。
    • 要在同一行显示多个字段,将这些字段包在自己的元组中。在这个例子中,urltitle 字段将显示在同一行,content 字段将显示在它们下面的一行:
      1
      2
      class FlatPageAdmin(admin.ModelAdmin):
      fields = (('url', 'title'), 'content')
    • 注释:这个 fields 选项不应与 fieldsets 选项中的 fields 字典键混淆,下一节将介绍。
    • 如果 fieldsfieldsets 选项都不存在,Django 将默认在一个单一的字段集中显示每个非 AutoField 且有 editable=True 的字段,顺序与模型中定义的字段相同。
  • fieldsets

    • 设置 fieldsets 来控制管理员 “添加” 和 “更改” 页面的布局。
    • fieldsets 是一个由两个元组组成的列表,其中每个元组代表管理表单页面上的一个 <fieldset>。(一个 <fieldset> 是表单的一个 “部分”。)
    • 这两个元组的格式是 (name, field_options),其中 name 是代表字段集标题的字符串,field_options 是关于字段集的信息字典,包括要在其中显示的字段列表。
    • 一个完整的例子,取自 django.contrib.flatpages.models.FlatPage 模型:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      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'),
      }),
      )
    • 这样一来,管理页面就变成了这样:
    • 如果 fieldsetsfields 选项都不存在,Django 将默认在一个单一的表单集中显示每个非 AutoField 且有 editable=True 的字段,顺序与模型中定义的字段相同。
    • field_options 字典可以有以下键:
      • fields
        • 要在该字段集中显示的字段名元组。这个键是必需的。
        • 举例:
          1
          2
          3
          {
          'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
          }
        • fields 选项一样,要在同一行显示多个字段,请将这些字段封装在自己的元组中。在这个例子中,first_namelast_name 字段将显示在同一行:
          1
          2
          3
          {
          'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
          }
        • fields 可以包含 readonly_fields 中定义的值,以只读方式显示。
        • 如果你将可调用的名称添加到 fields 中,与 fields 选项的规则相同:可调用的名称必须列在 readonly_fields 中。
      • classes
        • 一个包含额外 CSS 类的列表或元组,用于应用到字段集。
        • 举例:
          1
          2
          3
          {
          'classes': ('wide', 'extrapretty'),
          }
        • 默认的管理网站样式表定义的两个有用的类是 collapsewidecollapse 风格的字段集将在管理中被初始折叠,并被一个小的 “点击展开” 链接所取代;wide 风格的字段集将被赋予额外的水平空间。wide 风格的字段集将获得额外的水平空间。
      • description
        • 一串可选的额外文本,显示在每个字段集的顶部,在字段集的标题下。这个字符串在 TabularInline 中由于其布局的原因而无法显示。
        • 请注意,当这个值在管理界面显示时,它不是 HTML 转义后的。如果你愿意的话,这可以让你包含 HTML。或者你可以使用纯文本和 django.utils.html.escape() 来转义任何 HTML 特殊字符。
  • filter_horizontal

    默认情况下,在管理网站中显示一个 ManyToManyField<select multiple>。但是,多选框在选择很多项目时,会很难用。在这个列表中添加一个 ManyToManyField,就可以改用一个不显眼的 JavaScript “过滤器” 界面,在选项中进行搜索。未选择和选择的选项并排出现在两个框中。参见 filter_vertical 来使用垂直界面。

  • filter_vertical

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

  • form

    • 默认情况下,会为你的模型动态创建一个 ModelForm。它用于创建在添加/更改页面上显示的表单。你可以很容易地提供你自己的 ModelForm 来覆盖添加/更改页面上的任何默认表单行为。另外,你可以使用 ModelAdmin.get_form() 方法来定制默认的表单,而不是指定一个全新的表单。
    • 示例请参见 在管理中添加自定义验证 一节。
    • 注释:
      • 如果你在 ModelForm 上定义了 Meta.model 属性,你也必须定义 Meta.fields 属性(或 Meta.exclude 属性)。但是,由于管理有自己定义字段的方式,所以 Meta.field 属性将被忽略。
      • 如果 ModelForm 只用于管理,最简单的解决办法是省略 Meta.model 属性,因为 ModelAdmin 将提供正确的模型。或者,你可以在 Meta 类中设置 fields = [] 以满足 ModelForm 的验证。
    • 注解:
      • 如果你的 ModelFormModelAdmin 都定义了 exclude 选项,那么 ModelAdmin 优先:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        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
      • 在上面的例子中,“年龄” 字段将被排除,但 “姓名” 字段将被包含在生成的表单中。
  • formfield_overrides

    • 这提供了一个快速而简单的方法来覆盖一些 Field 选项,以便在管理中使用。formfield_overrides 是一个字典,它将字段类映射成一个参数的字典,以便在构造时传递给字段。
    • 由于这有点抽象,我们来看一个具体的例子。formfield_overrides 最常见的用法是为某一类型的字段添加一个自定义部件。所以,想象一下,我们写了一个 RichTextEditorWidget,我们想用于大文本字段,而不是默认的 <textarea>。下面是我们要做的:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      from django.contrib import admin
      from django.db import models

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

      class MyModelAdmin(admin.ModelAdmin):
      formfield_overrides = {
      models.TextField: {'widget': RichTextEditorWidget},
      }
    • 注意,字典中的键是实际的字段类,不是 字符串。值是另一个字典;这些参数将被传递给表单字段的 __init__() 方法。详见 表单 API
    • 警告:
      • 如果你想使用一个带有关系字段的自定义部件(例如 ForeignKeyManyToManyField),确保你没有在 raw_id_fieldsradio_fieldsautocomplete_fields 中包含该字段的名称。
      • formfield_overrides 不会让你改变有 raw_id_fieldsradio_fieldsautocomplete_fields 设置的关系字段上的部件。这是因为 raw_id_fieldsradio_fieldsautocomplete_fields 意味着自己的自定义部件。
  • inlines

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

  • list_display

    • 设置 list_display 来控制哪些字段显示在管理的变更列表页面。
    • 举例:
      1
      list_display = ('first_name', 'last_name')
    • 如果你不设置 list_display,管理网站将显示一个单列,显示每个对象的 __str__() 表示。
    • list_display 中可以使用四种类型的值。 除了最简单的之外,所有的都可以使用 display () 装饰器,它用于自定义字段的呈现方式:
      • 模型字段的名称。例如:
        1
        2
        class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'last_name')
      • 一个接受一个参数的可调用对象,即模型实例。例如:
        1
        2
        3
        4
        5
        6
        @admin.display(description='Name')
        def upper_case_name(obj):
        return ("%s %s" % (obj.first_name, obj.last_name)).upper()

        class PersonAdmin(admin.ModelAdmin):
        list_display = (upper_case_name,)
      • 表示 ModelAdmin 方法的字符串,该方法接受一个参数,即模型实例。例如:
        1
        2
        3
        4
        5
        6
        class PersonAdmin(admin.ModelAdmin):
        list_display = ('upper_case_name',)

        @admin.display(description='Name')
        def upper_case_name(self, obj):
        return ("%s %s" % (obj.first_name, obj.last_name)).upper()
      • 代表模型属性或方法的字符串(没有任何必要的参数)。例如:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        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):
        return '%d’s' % (self.birthday.year // 10 * 10)

        class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'decade_born_in')
    • 关于 list_display 要注意的几个特殊情况:
      • 如果字段是 ForeignKey,Django 会显示相关对象的 __str__()
      • ManyToManyField 字段不被支持,因为这需要为表中的每一行单独执行一条 SQL 语句。如果你还是想这样做,请给你的模型一个自定义方法,并将该方法的名称添加到 list_display 中。(更多关于 list_display 中的自定义方法,请参见下文)。
      • 如果字段是 BooleanField,Django 会显示一个漂亮的 “是”、“否” 或 “未知” 图标,而不是 TrueFalseNone
      • 如果给定的字符串是模型的一个方法,ModelAdmin 或者是一个可调用的方法,Django 默认会对输出进行 HTML 转义。如果要转义用户的输入,并允许你自己使用未转义的标签,可以使用 format_html()
    • 使用 list_display_links 来控制 list_display 中的字段是否以及哪些字段应该被链接到对象的 “更改” 页面。
    • 默认情况下,更改列表页将把第一列 —— list_display 中指定的第一个字段 —— 链接到每个项目的更改页面。但是 list_display_links 让你改变这一点:
      • 将其设置为 None,则完全没有链接。
      • 将它设置为一个列表或元组字段(格式与 list_display 相同),你希望将其列转换为链接。
      • 你可以指定一个或多个字段。只要字段出现在 list_display 中,Django 就不会关心链接了多少(或多少)字段。唯一的要求是,如果你想以这种方式使用 list_display_links,你必须定义 list_display
    • 在这个例子中,first_namelast_name 字段将在更改列表页面上被链接:
      1
      2
      3
      class PersonAdmin(admin.ModelAdmin):
      list_display = ('first_name', 'last_name', 'birthday')
      list_display_links = ('first_name', 'last_name')
    • 在这个例子中,更改列表页网格将没有链接:
      1
      2
      3
      class AuditEntryAdmin(admin.ModelAdmin):
      list_display = ('timestamp', 'message')
      list_display_links = None
  • list_editable

    • list_editable 设置为模型上允许在更改列表页上编辑的字段名称列表。也就是说,在 list_editable 中列出的字段将作为表单部件显示在变更列表页上,允许用户一次编辑和保存多行。
    • 备注:
      • list_editable 以特定方式与其他几个选项进行交互;你应该注意以下规则:
        • list_editable 中的任何字段都必须在 list_display 中。你不能编辑一个没有显示的字段!
        • 同一字段不能同时列在 list_editablelist_display_links 中 —— 一个字段不能既是表单又是链接。
      • 如果这些规则中的任何一条被破坏,你会得到一个验证错误。
  • list_filter

    • 设置 list_filter 以激活管理员更改列表页面右侧栏中的过滤器。
    • 最简单的 list_filter 采用字段名称的列表或元组来激活过滤,但还有几个更高级的选项可用。 有关详细信息,请参阅 ModelAdmin List Filters
  • list_max_show_all

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

  • list_per_page

    设置 list_per_page 来控制每个分页的管理变更列表页面上出现多少个项目。默认情况下,设置为 100

    • 设置 list_select_related 告诉 Django 在检索管理变更列表页的对象列表时使用 select_related()。这样可以省去一堆数据库查询。
    • 该值应是布尔值、列表或元组。默认值是 False
    • 当值为 True 时,select_related() 总是会被调用。当值设置为 False 时,Django 将查看 list_display,如果有 ForeignKey,则调用 select_related()
    • 如果你需要更精细的控制,可以使用元组(或列表)作为 list_select_related 的值。空元组将阻止 Django 调用 select_related。任何其他元组将直接传递给 select_related 作为参数。例如:
      1
      2
      class ArticleAdmin(admin.ModelAdmin):
      list_select_related = ('author', 'category')
    • 将调用 select_related('author', 'category')
    • 如果需要根据请求指定一个动态值,可以实现一个 get_list_select_related() 方法。
    • 备注:当 select_related() 已经在变更列表的 QuerySet 上被调用时,ModelAdmin 会忽略这个属性。
  • ordering

    • 设置 ordering 来指定对象列表在 Django 管理视图中的排序方式。这应该是一个列表或元组,格式与模型的 ordering 参数相同。
    • 如果没有提供,Django 管理员将使用模型的默认排序。
    • 如果你需要指定一个动态的顺序(例如取决于用户或语言),你可以实现一个 get_ordering() 方法。
    • 排序和分类的性能考虑:
      • 为了确保结果的确定性排序,如果不能找到一个单一的或唯一的字段集,提供总的排序,那么变更表就会在排序中增加 pk
      • 例如,如果默认的排序是按非唯一的 name 字段排序,那么更改列表就按 namepk 排序。如果你有很多行,而且在 namepk 上没有索引,这可能会表现得很差。
  • paginator

    用于分页的分页器类。默认情况下,使用 django.core.paginator.Paginator。如果自定义的分页器类没有和 django.core.paginator.Paginator 一样的构造函数接口,你还需要为 ModelAdmin.get_paginator() 提供一个实现。

  • prepopulated_fields

    • prepopulated_fields 设置为一个字典,将字段名称映射到它应该预先填充的字段:
      1
      2
      class ArticleAdmin(admin.ModelAdmin):
      prepopulated_fields = {"slug": ("title",)}
    • 当设置时,给定的字段将使用一点 JavaScript 从分配的字段中填充。这个功能的主要用途是从一个或多个其他字段自动生成 SlugField 字段的值。生成的值是通过连接源字段的值,然后将结果转化为有效的 slug(例如,用破折号代替空格,使用 ASCII 字母的小写字母)。
    • 预填充的字段在保存值后不会被 JavaScript 修改。通常情况下,不希望 slug 发生变化(如果对象中使用了 slug,会导致对象的 URL 发生变化)。
    • prepopulated_fields 不接受 DateTimeFieldForeignKeyOneToOneFieldManyToManyField 字段。
  • preserve_filters

    默认情况下,在创建、编辑或删除对象后,应用的过滤器会被保存在列表视图中。您可以通过将此属性设置为 False 来清除过滤器。

  • radio_fields

    • 默认情况下,Django 的管理对于 ForeignKey 或设置了 choices 的字段使用选择框界面(<select>)。如果字段存在于 radio_fields 中,Django 将使用单选按钮接口代替。假设 groupPerson 模型上的一个 ForeignKey
      1
      2
      class PersonAdmin(admin.ModelAdmin):
      radio_fields = {"group": admin.VERTICAL}
    • 你可以在 django.contrib.admin 模块中选择使用 HORIZONTALVERTICAL
    • 不要在 radio_fields 中包含一个字段,除非它是 ForeignKey 或已设置 choices
  • autocomplete_fields

    • autocomplete_fields 是一个 ForeignKey 和/或 ManyToManyField 字段的列表,你想将其改为 Select2 自动完成输入。
    • autocomplete_fields 是一个 ForeignKey 和/或的列表,默认情况下,管理对这些字段使用选择框接口(<select>)。有时你不想产生选择所有相关实例在下拉中显示的开销。ManyToManyField 字段你想改成 Select2 自动完成输入。
    • Select2 输入看起来与默认输入类似,但自带搜索功能,异步加载选项。如果相关模型有很多实例,这样会更快、更方便用户使用。
    • 你必须在相关对象的 ModelAdmin 上定义 search_fields,因为自动完成搜索使用它。
    • 为了避免未经授权的数据泄露,用户必须拥有相关对象的 viewchange 权限才能使用自动完成。
    • 结果的排序和分页由相关的 ModelAdminget_ordering()get_paginator() 方法控制。
    • 在下面的例子中,ChoiceAdminQuestion 有一个 ForeignKey 的自动完成字段。结果由 question_text 字段过滤,并由 date_created 字段排序:
      1
      2
      3
      4
      5
      6
      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 属性的默认实现。
  • raw_id_fields

    • 默认情况下,Django 的管理员对 ForeignKey 的字段使用选择框接口(<select>)。有时候,你不想产生必须选择所有相关的实例来显示在下拉框中的开销。
    • raw_id_fields 是你想改变为 ForeignKeyManyToManyFieldInput 部件的字段列表:
      1
      2
      class ArticleAdmin(admin.ModelAdmin):
      raw_id_fields = ("newspaper",)
    • raw_id_fieldsInput 部件应该包含一个主键,如果该字段是 ForeignKey。或者是一个逗号分隔的值列表,如果该字段是 ManyToManyFieldraw_id_fields 部件在字段旁边显示一个放大镜按钮,允许用户搜索和选择一个值:
  • readonly_fields

    • 默认情况下,管理会将所有字段显示为可编辑。该选项中的任何字段(应该是 listtuple)将按原样显示其数据,不可编辑;它们也被排除在用于创建和编辑的 ModelForm 中。请注意,当指定 ModelAdmin.fieldsModelAdmin.fieldsets 时,只读字段必须存在才能显示(否则将被忽略)。
    • 如果没有通过 ModelAdmin.fieldsModelAdmin.fielets 定义明确的顺序就使用 readonly_fields,它们将在所有可编辑字段之后最后添加。
    • 一个只读字段不仅可以显示模型字段的数据,还可以显示模型的方法或 ModelAdmin 类本身的方法的输出。这与 ModelAdmin.list_display 的行为方式非常相似。这提供了一种方法来使用管理员接口来提供被编辑对象的状态反馈,例如:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      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,在管理更改表格时启用 “另存为新” 功能。
    • 通常情况下,对象有三个保存选项。“保存”、“保存并继续编辑” 和 “保存并添加另一个”。如果 save_asTrue,则 “保存并添加另一个” 将被 “另存为新” 按钮所取代,该按钮将创建一个新的对象(具有新的 ID),而不是更新现有的对象。
    • 默认情况下,save_as 被设置为 False
  • save_as_continue

    • save_as=True 时,保存新对象后默认重定向到该对象的变更视图。如果设置 save_as_continue=False,则重定向到变更列表视图。
    • 默认情况下,save_as_continue 被设置为 True
  • save_on_top

    • 设置 save_on_top 来在你的管理更改表格的顶部添加保存按钮。
    • 通常情况下,保存按钮只出现在表格的底部。如果设置 save_on_top,按钮将同时出现在顶部和底部。
    • 默认情况下,save_on_top 被设置为 False
  • search_fields

    • 设置 search_fields,在管理更改列表页面上启用搜索框。这应该被设置为字段名的列表,每当有人在该文本框中提交搜索查询时,就会被搜索到。
    • 这些字段应该是某种文本字段,如 CharFieldTextField。你也可以对 ForeignKeyManyToManyField 进行相关查询,并使用查找 API “follow” 符号:
      1
      search_fields = ['foreign_key__related_fieldname']
    • 例如,如果你有一个有作者的博客条目,下面的定义将可以通过作者的电子邮件地址搜索博客条目:
      1
      search_fields = ['user__email']
    • 当有人在管理搜索框中进行搜索时,Django 会将搜索查询拆分成多个词,并返回所有包含这些词的对象,不区分大小写(使用 icontains 查找),其中每个词必须在 search_fields 中至少有一个。例如,如果 search_fields 设置为 ['first_name', 'last_name'],用户搜索 john lennon',Django 会做相当于这个 SQL WHERE 子句。
      1
      2
      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 子句:
      1
      WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')
    • 如果你不想使用 icontains 作为查找,你可以通过附加字段来使用任何查找。例如,你可以通过设置 search_fields['first_name__exact'] 来使用 exact
    • 还可以使用一些(较老的)快捷方式来指定字段查找。你可以在 search_fields 中的字段前加上以下字符,相当于在字段中加上 __<lookup>
      前缀 查找
      ^ startswith
      = iexact
      @ search
      None icontains
    • 如果你需要自定义搜索,你可以使用 ModelAdmin.get_search_results() 来提供额外的或替代的搜索行为。
  • search_help_text

    • New in Django 4.0.
    • 设置 search_help_text,为搜索框指定一个描述性文本,显示在它的下面。
  • show_full_result_count

    • 设置 show_full_result_count 来控制是否应该在过滤后的管理页面上显示全部对象的数量(例如: 99 results (103 total))。如果这个选项被设置为 False,则会显示 99 results (Show all) 这样的文字。
    • 默认的 show_full_result_count=True 会生成一个对表进行完整计数的查询,如果表包含大量的行,那么这个查询可能会很昂贵。
  • sortable_by

    • 默认情况下,变更列表页面允许按 list_display 中指定的所有模型字段(以及使用 display() 装饰器的 ordering 参数或具有 admin_order_field 属性的可调用对象)进行排序。
    • 如果你想禁止对某些列进行排序,请将 sortable_by 设置为你想排序的 list_display 子集的一个集合(例如 listtupleset)。一个空的集合会禁用所有列的排序。
    • 如果你需要动态地指定这个列表,可以实现一个 get_sortable_by() 方法来代替。
  • view_on_site

    • 设置 view_on_site 来控制是否显示 “在站点上查看” 链接。这个链接应该把你带到一个可以显示保存对象的 URL。
    • 这个值可以是一个布尔标志,也可以是一个可调用对象。如果 True (默认),对象的 get_absolute_url() 方法将被用来生成网址。
    • 如果你的模型有一个 get_absolute_url() 方法,但你不想让 “在站点上查看” 按钮出现,你只需要将 view_on_site 设置为 False
      1
      2
      3
      4
      from django.contrib import admin

      class PersonAdmin(admin.ModelAdmin):
      view_on_site = False
    • 如果它是一个可调用对象,它接受模型实例作为参数。例如:
      1
      2
      3
      4
      5
      6
      7
      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
  • 简单示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    from django.contrib import admin

    from user.models import User


    # Register your models here.
    class UserAdmin(admin.ModelAdmin):
    # 设置显示哪些字段
    list_display = ('username', 'phone', 'first_name', 'last_name', 'date_joined')
    # 设置每页的记录数,默认为100条
    list_per_page = 10
    # 排序,使用“-”以降序排列
    ordering = ('-date_joined',)
    # 设置默认可编辑字段
    list_editable = ('phone', 'first_name', 'last_name')
    # 过滤查询
    list_filter = ('username', 'phone', 'first_name')
    # 搜索查询
    search_fields = ('username',)
    # 为搜索框指定一个描述性文本,显示在搜索框的下面
    search_help_text = '通过用户名进行搜索'
    # 日期的等级划分
    date_hierarchy = 'date_joined'


    admin.site.register(User, UserAdmin)
    admin.site.site_header = '未来鲜生后台管理'
    admin.site.site_title = '未来鲜生'
  • save_model

    • save_model 方法被赋予 HttpRequest、一个模型实例、一个 ModelForm 实例和一个基于是否添加或更改对象的布尔值。覆盖这个方法可以进行保存前或保存后的操作。调用 super().save_model() 使用 Model.save() 保存对象。
    • 例如,在保存之前将 request.user 附加到对象上:
      1
      2
      3
      4
      5
      6
      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

    delete_model 方法被赋予 HttpRequest 和一个模型实例。覆盖该方法可以进行删除前或删除后的操作。调用 super().delete_model() 使用 Model.delete()` 删除对象。

  • delete_queryset

    delete_queryset() 方法是给定 HttpRequest 和一个 QuerySet 要删除的对象。重写该方法,可以自定义 “删除选定对象” 的删除过程 动作

  • save_formset

    • save_formset 方法被赋予 HttpRequest、父 ModelForm 实例和一个基于是否添加或更改父对象的布尔值。
    • 例如,将 request.user 附加到每一个改变了的表单集模型实例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      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

    get_ordering 方法以 request 为参数,并期望返回一个类似于 ordering 属性的 listtuple 的排序。例如:

    1
    2
    3
    4
    5
    6
    7
    class PersonAdmin(admin.ModelAdmin):

    def get_ordering(self, request):
    if request.user.is_superuser:
    return ['name', 'rank']
    else:
    return ['name']
  • get_search_results

    • get_search_results 方法将显示的对象列表修改为符合所提供的搜索词的对象。它接受请求、应用当前过滤器的查询集和用户提供的搜索词。它返回一个元组,其中包含一个修改后实现搜索的查询集,以及一个布尔值,表示结果是否包含重复。
    • 默认的实现是搜索 ModelAdmin.search_fields 中命名的字段。
    • 此方法可能会被您自己的自定义搜索方法覆盖。 例如,您可能希望按整数字段进行搜索,或使用外部工具(如 SolrHaystack)。 您必须确定您的搜索方法实现的查询集更改是否可能会在结果中引入重复项,并在返回值的第二个元素中返回 True。
    • 例如,如果要按 nameage 进行搜索,你可以使用:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      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

    get_autocomplete_fields() 方法被赋予 HttpRequest,预计将返回一个 listtuple 字段名,这些字段名将与自动完成部件一起显示,如上面 ModelAdmin.autocomplete_fields 部分所述。

  • get_readonly_fields

    get_readonly_fields 方法是给定 HttpRequest 和被编辑的 obj(或者在添加表单中给定 None),并期望返回一个 listtuple 的字段名,这些字段名将被显示为只读,如上面 ModelAdmin.readonly_fields 部分所述。

  • get_prepopulated_fields

    get_prepopulated_fields 方法是给定 HttpRequest 和被编辑的 obj (或者在添加表单中给定 None),并期望返回一个 dictionary,如上面 ModelAdmin.prepopulated_fields 一节所述。

  • get_list_display

    get_list_display 方法被赋予 HttpRequest,预计将返回一个 listtuple 的字段名,这些字段名将显示在变更列表视图上,如上面 ModelAdmin.list_display 一节所述。

  • get_list_display_links 方法被赋予 HttpRequest 和由 ModelAdmin.get_list_display() 返回的 listtuple。如 ModelAdmin.list_display_links 一节所述,预计它将返回变化列表中的 Nonelisttuple 字段名,这些字段名将被链接到变化视图。

  • get_exclude

    get_exclude 方法是给定 HttpRequest 和被编辑的 obj (或者在添加表单中给定 None),并期望返回一个字段列表,如 ModelAdmin.exclude 中所述。

  • get_fields

    get_fields 方法是给定 HttpRequest 和被编辑的 obj (或者在添加表单中给定 None),并期望返回一个字段列表,如上面 ModelAdmin.fields 一节所述。

  • get_fieldsets

    get_fieldsets 方法是给定 HttpRequest 和被编辑的 obj (或者在添加表单中给定 None),预计将返回一个双元组列表,其中每个双元组代表管理表单页面上的 <fieldset>,如上面 ModelAdmin.fieldsets 部分所述。

  • get_list_filter

    get_list_filter 方法被赋予 HttpRequest,并期望返回与 list_filter 属性相同的序列类型。

  • get_list_select_related 方法被赋予 HttpRequest,应该像 ModelAdmin.list_select_related 那样返回一个布尔值或列表。

  • get_search_fields

    get_search_fields 方法被赋予 HttpRequest,并期望返回与 search_fields 属性相同的序列类型。

  • get_sortable_by

    • get_sortable_by() 方法被传递给 HttpRequest,并期望返回一个字段名的集合(例如 listtupleset),这些字段名将在更改列表页中被排序。
    • get_sortable_by() 方法被传递给 HttpRequest,并期望返回一个字段名的集合(例如 listtupleset),这些字段名将在更改列表页中被排序。
    • 例如,要防止一列或多列无法排序:
      1
      2
      3
      4
      class PersonAdmin(admin.ModelAdmin):

      def get_sortable_by(self, request):
      return {*self.get_list_display(request)} - {'rank'}
  • get_inline_instances

    • get_inline_instances 方法被赋予 HttpRequest 和正在编辑的 obj(或添加表单上的 None),并且预期返回 InlineModelAdmin 对象的 listtuple,如下面的 InlineModelAdmin 部分所述。 例如,以下将返回没有基于添加、更改、删除和查看权限的默认过滤的内联:
      1
      2
      3
      4
      5
      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 中定义的类的实例,否则在添加相关对象时可能会遇到 “Bad Request” 错误。
  • get_inlines

    get_inlines 方法是给定 HttpRequest 和被编辑的 obj (或在添加表单中给定 None),并期望返回一个可迭代对象的内联。你可以覆盖这个方法,根据请求或模型实例动态添加内联,而不是在 ModelAdmin.inlines 中指定它们。

  • get_urls

    • ModelAdmin 上的 get_urls 方法以与 URLconf 相同的方式返回要用于该 ModelAdmin 的 URL。 因此,您可以按照 URL 调节器中的说明扩展它们,在您的视图上使用 AdminSite.admin_view() 包装器:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      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 扩展:
      1
      2
      3
      4
      {% extends "admin/base_site.html" %}
      {% block content %}
      ...
      {% endblock %}
    • 如果页面是可缓存的,但你仍然希望进行权限检查,你可以传递一个 cacheable=True 参数到 AdminSite.admin_view()
      1
      path('my_view/', self.admin_site.admin_view(self.my_view, cacheable=True))
    • ModelAdmin 视图有 model_admin 属性。其他 AdminSite 视图有 admin_site 属性。
  • get_form

    • 返回一个 ModelForm 类,用于管理员添加和更改视图,参见 add_view()change_view()
    • 基本实现使用 modelform_factory() 来子类 form,通过 fieldsexclude 等属性进行修改。所以,例如,如果你想为超级用户提供额外的字段,你可以像这样换一个不同的基本表单:
      1
      2
      3
      4
      5
      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 类。
  • get_formsets_with_inlines

    • 产生 (FormSet, InlineModelAdmin) 对,用于管理添加和更改视图。
    • 例如,如果你想只在变化视图中显示一个特定的内联,你可以覆盖 get_formsets_with_inlines 如下:
      1
      2
      3
      4
      5
      6
      7
      8
      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

    • ModelAdmin 上的 formfield_for_foreignkey 方法允许你覆盖外键字段的默认 formfield。例如,要根据用户返回这个外键字段的对象子集:
      1
      2
      3
      4
      5
      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 进行过滤(参见 处理关系的字段)。例如:
      1
      2
      3
      4
      5
      6
      7
      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_manytomany

    • formfield_for_foreignkeyformfield_for_manytomany 方法一样,formfield_for_choice_field 方法可以被重写,以改变已声明选择的字段的默认字段。例如,如果超级用户的选择与普通员工的选择不同,你可以按以下步骤进行:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      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 失败。
  • get_changelist

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

  • get_changelist_form

    • 返回一个 ModelForm 类,供变更列表页面中的 Formset 使用。要使用一个自定义表单,例如:
      1
      2
      3
      4
      5
      6
      7
      8
      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 属性)。然而,ModelAdmin 会忽略这个值,用 ModelAdmin.list_editable 属性来覆盖它。最简单的解决办法是省略 Meta.model 属性,因为 ModelAdmin 将提供正确的模型使用。
  • get_changelist_formset

    如果使用了 list_editable,则返回一个 ModelFormSet 类,供变更列表页面使用。要使用自定义表单集,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)
  • lookup_allowed

    • 变更列表页面中的对象可以通过 URL 的查询字符串进行过滤。例如 list_filter 就是这样工作的。这些查询类似于 QuerySet.filter() (例如 user__email=user@example.com)。由于用户可以对查询字符串中的查找进行操作,因此必须对它们进行处理,以防止未经授权的数据暴露。
    • lookup_allowed() 方法从查询字符串(如 'user__email')和相应的值(如 user@example.com)中得到一个查找路径,并返回一个布尔值,表示是否允许使用参数过滤变更列表的 QuerySet。如果 lookup_allowed() 返回 False,则会引发 DisallowedModelAdminLookupSuspiciousOperation 的子类)。
    • 默认情况下,lookup_allowed() 允许访问模型的本地字段、在 list_filter 中使用的字段路径(但不包括 get_list_filter())中使用的字段路径,以及 limit_choices_toraw_id_fields 中正确运行所需的查找。
    • 重写这个方法来定制你的 ModelAdmin 子类允许的查找。
  • has_view_permission

    • 如果允许查看 obj,应返回 True,否则返回 False。如果 obj 是 None,应返回 TrueFalse 表示是否允许查看该类型的对象(例如,False 将被解释为当前用户不允许查看该类型的任何对象)。
    • 如果用户有 “更改” 或 “查看” 权限,默认的实现将返回 True。
  • has_add_permission

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

  • has_change_permission

    如果允许编辑 obj,应返回 True,否则应返回 False。如果 objNone,应返回 TrueFalse 表示是否允许编辑该类型对象(例如,False 将被解释为当前用户不允许编辑该类型的任何对象)。

  • has_delete_permission

    如果允许删除 obj,应返回 True,否则返回 False。如果 objNone,应返回 TrueFalse,以表明是否允许删除该类型的对象(例如,False 将被解释为当前用户不允许删除该类型的任何对象)。

  • has_module_permission

    如果允许在管理员索引页上显示模块和访问模块的索引页,应该返回 True,否则返回 False。默认使用 User.has_module_perms()。覆盖它并不限制对视图的访问,添加、更改或删除视图, has_view_permission()has_add_permission()has_change_permission()has_delete_permission() 应该用于此。

  • get_queryset

    ModelAdmin 上的 get_queryset 方法返回一个 QuerySet 的所有模型实例,这些实例可以被管理网站编辑。覆盖该方法的一个用例是显示登录用户拥有的对象:

    1
    2
    3
    4
    5
    6
    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)
  • message_user

    • 使用 django.contrib.messages 后台向用户发送消息。 参见 自定义 ModelAdmin 示例
    • 关键字参数允许你改变消息的级别,添加额外的 CSS 标签,或者在没有安装 contrib.messages 框架的情况下无声地失败。这些关键字参数与 django.contrib.messages.add_message() 的参数一致,更多细节请参见该函数的文档。一个不同的地方是,除了整数/常量之外,级别还可以作为字符串标签传递。
  • get_paginator

    返回要用于该视图的分页器实例。默认情况下,实例化一个 paginator 的实例。

  • response_add

    • 确定 add_view() 阶段的 HttpResponse
    • response_add 在提交管理表单后,对象和所有相关实例被创建和保存后被调用。你可以覆盖它来改变对象创建后的默认行为。
  • response_change

    • 确定 change_view() 阶段的 HttpResponse
    • response_change 在管理表单提交后,对象和所有相关实例被保存后被调用。你可以覆盖它来改变对象被改变后的默认行为。
  • response_delete

    • delete_view() 阶段确定 HttpResponse
    • response_delete 在对象被删除后被调用。你可以覆盖它来改变对象被删除后的默认行为。
    • obj_display 是删除对象名称的字符串。
    • obj_id 是用于检索要删除的对象的序列化标识符。
  • get_formset_kwargs

    • 一个用于自定义传递给表单集构造函数的关键字参数的钩子。例如,将 request 传递给表单集表单:
      1
      2
      3
      4
      5
      6
      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},
      }
    • 您还可以使用它来设置表单的初始值。
  • get_changeform_initial_data

    • 一个钩子,用于管理更改表格的初始数据。默认情况下,字段的初始值来自 GET 参数。例如,?name=initial_value 将把 name 字段的初始值设置为 initial_value
    • 这个方法应该返回一个形式为 {'fieldname': 'fieldval'} 的字典:
      1
      2
      def get_changeform_initial_data(self, request):
      return {'name': 'custom_initial_value'}
  • get_deleted_objects

    • 一个钩子,用于自定义 delete_view() 和 “删除已选” 动作 的删除过程。
    • objs 参数是要删除的对象(一个 QuerySet 或模型实例列表)的等价可迭代对象,requestHttpRequest
    • 这个方法必须返回一个四元元组 (delete_objects, model_count, perms_needed, protected)
    • deleted_objects 是一个代表所有将被删除对象的字符串列表。如果有任何相关的对象要删除,则列表是嵌套的,包括这些相关对象。该列表在模板中使用 unordered_list 过滤器进行格式化。
    • model_count 是一个将每个模型的 verbose_name_plural 映射到将被删除的对象数量的字典。
    • perms_needed 是一组 verbose_name 的用户没有权限删除的模型。
    • protected 是一个字符串列表,代表所有不能删除的受保护相关对象。该列表显示在模板中。
  • 说明

    • 一个 Django 管理站点由 django.contrib.admin.sites.AdminSite 的实例来表示;默认情况下,这个类的实例被创建为 django.contrib.admin.site,你可以用它来注册你的模型和 ModelAdmin 实例。
    • 如果你想自定义默认的管理站点,你可以 覆盖它
    • 当构造一个 AdminSite 的实例时,你可以使用构造函数的 name 参数提供一个唯一的实例名称。这个实例名是用来标识实例的,特别是在 反查管理 URL 时。如果没有提供实例名,将使用默认的实例名 admin。参见 自定义 AdminSite 类,了解定制 AdminSite 类的例子。
  • AdminSite 属性

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

    • site_title

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

    • site_url

      • 每个管理页面顶部的 “查看网站” 链接的 URL。默认情况下,site_url/。将其设置为 None 以删除该链接。
      • 对于运行在子路径上的站点, each_context() 方法会检查当前请求是否设置了 request.META['SCRIPT_NAME'],如果 site_url 没有设置为 / 以外的内容,则使用该值。
    • index_title

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

    • index_template

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

    • app_index_template

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

    • empty_value_display

      用于在管理站点的更改列表中显示空值的字符串。默认值为破折号。该值也可以在每个 ModelAdmin 的基础上被覆盖,也可以在 ModelAdmin 内的自定义字段上设置 empty_value_display 属性。参见 ModelAdmin.empty_value_display 的例子。

    • enable_nav_sidebar

      一个布尔值,决定是否在大屏幕上显示导航侧栏。默认情况下,它被设置为 True

    • final_catch_all_view

      • 一个布尔值,用于决定是否在管理员中添加一个最终的总括视图,将未认证的用户重定向到登录页面。默认情况下,它被设置为 True
      • 警告:不建议将此设置为 False,因为该视图可以保护潜在的模型枚举隐私问题。
    • login_template

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

    • login_form

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

    • logout_template

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

    • password_change_template

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

    • password_change_done_template

      自定义模板的路径,该模板将被管理员网站密码修改完成后的视图使用。

  • AdminSite 方法

    • each_context

      • 返回一个变量字典,将其放入管理站点中每个页面的模板上下文中。
      • 默认情况下包括以下变量和值:
        • site_headerAdminSite.site_header
        • site_titleAdminSite.site_title
        • site_urlAdminSite.site_url
        • has_permissionAdminSite.has_permission()
        • available_apps :当前用户可用的 application registry 中的应用程序列表。列表中的每个条目都是一个代表应用程序的字典,其键如下:
          • app_label :应用程序标签
          • app_url :管理中应用程序索引的 URL
          • has_module_perms :一个布尔值,表示是否允许当前用户显示和访问模块的索引页
          • models :应用程序中可用模型的清单
            每个模型都是一个带有以下键的字典
          • model` :模型类
          • object_name :模型类名
          • name :模型的复数名
          • permsdict 跟踪 addchangedeleteview 权限
          • admin_url :模型的管理变更表 URL
          • add_url :添加新模型实例的管理网址
    • get_app_list

      • 返回当前用户可用的应用程序注册表中的应用程序列表。 您可以选择传递 app_label 参数以获取单个应用程序的详细信息。 列表中的每个条目都是一个字典,表示具有以下键的应用程序:
        • app_label :应用程序标签
        • app_url :管理中应用程序索引的 URL
        • has_module_perms :一个布尔值,表示是否允许当前用户显示和访问模块的索引页
        • models :应用程序中可用模型的清单
        • name: name of the application
          Each model is a dictionary with the following keys:
        • model` :模型类
        • object_name :模型类名
        • name :模型的复数名
        • permsdict 跟踪 addchangedeleteview 权限
        • admin_url :模型的管理变更表 URL
        • add_url :添加新模型实例的管理网址
      • 应用程序和模型列表按名称的字母顺序排序。 您可以覆盖此方法以更改管理索引页面上的默认顺序。
    • has_permission

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

    • register

      • 用给定的 admin_class 注册给定的模型类(或类的迭代)。admin_class 默认为 ModelAdmin (默认的管理选项)。如果给定了关键字参数 —— 例如 list_display —— 它们将作为选项应用到管理类中。
      • 如果一个模型是抽象的,会引发 ImproperlyConfigured,如果一个模型已经注册,会引发 django.contrib.admin.sites.AlreadyRegistered
    • unregister

      • 取消注册给定的模型类(或类的可迭代对象)
      • 如果一个模型还没有注册,就会引发 django.contrib.admin.sites.NotRegistered