Django站点管理——管理站点

参考文献:

https://docs.djangoproject.com/zh-hans/2.0/ref/contrib/admin/

Django的admin站点

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

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

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

概览

在startproject使用的默认项目模板中启用了admin。

扫描二维码关注公众号,回复: 2407761 查看本文章

供参考,以下是要求:

  1. 将“django.contrib.admin”添加到INSTALLED_APPS设置中。
  2. 管理员有四个依赖项 - django.contrib.auth,django.contrib.contenttypes,django.contrib.messages和django.contrib.sessions。 如果这些应用程序不在您的INSTALLED_APPS列表中,请添加它们。
  3. 将django.contrib.auth.context_processors.auth和Django.contrib.messages.context_processors.messages添加到TEMPLATES中定义的DjangoTemplates后端的'context_processors'选项以及django.contrib.auth.middleware.AuthenticationMiddleware和Django.contrib.messages。 middleware.MessageMiddleware到MIDDLEWARE。 默认情况下这些都是活动的,因此如果您手动调整设置,则只需执行此操作。
  4. 确定应在管理界面中编辑哪些应用程序模型。
  5. 对于每个模型,可以选择创建一个ModelAdmin类,该类封装了该特定模型的自定义管理功能和选项。
  6. 实例化AdminSite并告诉它每个模型和ModelAdmin类。
  7. 将AdminSite实例挂钩到您的URLconf中。

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

其他要点:

ModelAdmin 对象

class ModelAdmin

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

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

class AuthorAdmin(admin.ModelAdmin):
    pass
admin.site.register(Author, AuthorAdmin)

当然,如果你只想用默认的,不需要自定制的话,那么只需做以下操作即可:

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

admin.site.register(Author)

寄存器装饰器

register(*models, site=django.admin.sites.site)

还有一个用于注册ModelAdmin类的装饰器:

from django.contrib import admin
from .models import Author

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    pass

它给了一个或多个模型类来注册ModelAdmin。 如果您使用的是自定义AdminSite,请使用site关键字参数传递它:

from django.contrib import admin
from .models import Author, Editor, Reader
from myproject.admin_site import custom_admin_site

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

如果必须在其__init __()方法中引用模型管理类,则不能使用此装饰器,例如 super(PersonAdmin,self).__ init __(* args,** kwargs)。 你可以使用super().__ init __(* args,** kwargs)。

admin文件的搜索

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

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

class apps.SimpleAdminConfig
此类的工作方式与AdminConfig类似,不同之处在于它不调用autodiscover()。

autodiscover()
此函数尝试在每个已安装的应用程序中导入管理模块。 预计此类模块将向管理员注册模型。

通常,您不需要直接调用此函数,因为当Django启动时AdminConfig会调用它。

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

ModelAdmin选项

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

from django.contrib import admin

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

ModelAdmin.actions
在可更改的列表页面上提供可操作的功能列表。 有关详情,请参阅管理操作

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom
控制操作栏显示在页面上的位置。 默认情况下,管理员更改列表会在页面顶部显示操作(actions_on_top = True; actions_on_bottom = False)。

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

ModelAdmin.date_hierarchy
将date_hierarchy设置为模型中DateField或DateTimeField的名称,更改列表页面将包含该字段的基于日期的向下钻取导航。

例如:

date_hierarchy = 'pub_date'

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

date_hierarchy = 'author__pub_date'

这将基于可用数据智能地填充自身,例如, 如果所有日期都在一个月内,它将仅显示日级向下钻取。

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

ModelAdmin.empty_value_display

此属性会覆盖记录的空字段(无,空字符串等)的默认显示值。 默认值为 - (破折号)。 例如:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    empty_value_display = '-empty-'

您还可以使用AdminSite.empty_value_display覆盖所有管理页面的empty_value_display,或者对于以下特定字段:

from django.contrib import admin

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

    def view_birth_date(self, obj):
        return obj.birth_date

    view_birth_date.empty_value_display = '???'

ModelAdmin.exclude

如果给定此属性,则应该是要从表单中排除的字段名称列表。

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

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3)
    birth_date = models.DateField(blank=True, null=True)

如果您希望Author模型的表单仅包含name和title,您可以指定字段或排除如下:

from django.contrib import admin

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

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

由于Author模型只有三个字段,name,title和birth_date,因此上述声明产生的表单将包含完全相同的字段。

ModelAdmin.fields

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

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

在上面的示例中,只有字段url,title和content将按顺序显示在表单中。 字段可以包含在ModelAdmin.readonly_fields中定义的值,以显示为只读。有关更复杂的布局需求,请参阅fieldsets选项。

与list_display不同,fields选项可能只包含模型上的字段名称或表单指定的表单。 它只有在readonly_fields中列出时才包含callable。

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

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

注意:不应将此字段选项与fieldsets选项中的字段字典键混淆,如下一节中所述。

如果既没有字段也没有字段集选项,Django将默认显示除AutoField外的每个字段,并且在单个字段集中具有editable = True,其顺序与模型中定义的字段的顺序相同。

ModelAdmin.fieldsets

设置字段集以控制管理“添加”和“更改”页面的布局。

fieldsets是两元组的列表,其中每个二元组表示管理表单页面上的<fieldset>。 (<fieldset>是表单的“部分”。)

两元组的格式为(name,field_options),其中name是表示字段集标题的字符串,field_options是有关字段集的信息字典,包括要在其中显示的字段列表。

一个完整的例子,取自django.contrib.flatpages.models.FlatPage模型:

from django.contrib import admin

class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {
            'fields': ('url', 'title', 'content', 'sites')
        }),
        ('Advanced options', {
            'classes': ('collapse',),
            'fields': ('registration_required', 'template_name'),
        }),
    )

这会导致管理页面看起来像:

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

如果既不存在fieldsets也不存在fields选项,Django将默认显示每个不是AutoField的字段,并且在单个字段集中具有editable = True,其顺序与模型中定义的字段的顺序相同。

field_options字典可以包含以下键:

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

      例:

      {
      'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
      }

      与fields选项一样,要在同一行上显示多个字段,请将这些字段包装在自己的元组中。 在此示例中,first_name和last_name字段将显示在同一行上:

      {
      'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
      }

      字段可以包含在readonly_fields中定义的值,以显示为只读。

      如果将可调用的名称添加到字段,则应用与fields选项相同的规则:callable必须在readonly_fields中列出。

  • classes
    • 包含要应用于fieldset的额外CSS类的列表或元组。

      例:

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

      默认管理站点样式表定义的两个有用的类是折叠和宽泛的。 具有折叠样式的字段集最初将在管理员中折叠,并替换为小的“单击以展开”链接。 具有宽样式的场集将被赋予额外的水平空间。

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

      请注意,当该值显示在管理界面中时,该值不会被HTML转义。 如果您愿意,可以包含HTML。 或者,您可以使用纯文本和django.utils.html.escape()来转义任何HTML特殊字符。

ModelAdmin.filter_horizontal

默认情况下,管理站点中会显示一个带有<select multiple>的ManyToManyField。 但是,在选择多个项目时,多选框可能难以使用。 将ManyToManyField添加到此列表将改为使用一个漂亮的不显眼的JavaScript“过滤器”界面,允许在选项中进行搜索。 未选择和选定的选项并排显示在两个框中。 请参阅filter_vertical以使用垂直界面。

ModelAdmin.filter_vertical

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

ModelAdmin.form

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

有关示例,请参阅向管理员添加自定义验证部分。

注意:

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

如果ModelForm仅用于管理员,最简单的解决方案是省略Meta.model属性,因为ModelAdmin将提供正确的模型以供使用。 或者,您可以在Meta类中设置fields = []以满足ModelForm上的验证。

注意:

如果ModelForm和ModelAdmin都定义了排除选项,则ModelAdmin优先:

from django import forms
from django.contrib import admin
from myapp.models import Person

class PersonForm(forms.ModelForm):

    class Meta:
        model = Person
        exclude = ['name']

class PersonAdmin(admin.ModelAdmin):
    exclude = ['age']
    form = PersonForm

在上面的示例中,将排除“age”字段,但“name”字段将包含在生成的表单中。

ModelAdmin.formfield_overrides

这提供了一种快速而肮脏的方式来覆盖在管理中使用的一些Field选项。 formfield_overrides是一个字典,它将字段类映射到在构造时传递给字段的参数的字典。

由于这有点抽象,让我们看一个具体的例子。 formfield_overrides最常见的用途是为特定类型的字段添加自定义窗口小部件。 因此,假设我们编写了一个RichTextEditorWidget,我们希望将其用于大文本字段而不是默认的<textarea>。 这是我们如何做到这一点:

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

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

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

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

警告:

如果要使用具有关系字段的自定义窗口小部件(即ForeignKey或ManyToManyField),请确保未在raw_id_fields,radio_fields或autocomplete_fields中包含该字段的名称。

formfield_overrides不允许您更改设置了raw_id_fields,radio_fields或autocomplete_fields的关系字段上的窗口小部件。 那是因为raw_id_fields,radio_fields和autocomplete_fields意味着他们自己的自定义小部件。

ModelAdmin.inlines

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

ModelAdmin.list_display

设置list_display以控制在管理员的更改列表页面上显示的字段。

例如:

list_display = ('first_name', 'last_name')

如果未设置list_display,则管理站点将显示一个列,该列显示每个对象的__str __()表示形式。

您可以在list_display中使用四个可能的值:

  • 模型的一个字段,如下:
    • class PersonAdmin(admin.ModelAdmin):
          list_display = ('first_name', 'last_name')
  • 可调用,接受模型实例的一个参数, 如下:
    • def upper_case_name(obj):
          return ("%s %s" % (obj.first_name, obj.last_name)).upper()
      upper_case_name.short_description = 'Name'
      
      class PersonAdmin(admin.ModelAdmin):
          list_display = (upper_case_name,)
  • 表示ModelAdmin上的属性的字符串, 这与可调用的行为相同, 如下:
    • class PersonAdmin(admin.ModelAdmin):
          list_display = ('upper_case_name',)
      
          def upper_case_name(self, obj):
              return ("%s %s" % (obj.first_name, obj.last_name)).upper()
          upper_case_name.short_description = 'Name'
  • 表示模型上属性的字符串。 这与callable几乎相同,但在此上下文中self是模型实例, 如下:
    • from django.contrib import admin
      from django.db import models
      
      class Person(models.Model):
          name = models.CharField(max_length=50)
          birthday = models.DateField()
      
          def decade_born_in(self):
              return self.birthday.strftime('%Y')[:3] + "0's"
          decade_born_in.short_description = 'Birth decade'
      
      class PersonAdmin(admin.ModelAdmin):
          list_display = ('name', 'decade_born_in')

关于list_display的一些特殊情况需要注意:

  • 如果该字段是ForeignKey,Django将显示相关对象的__str __()。

  • 不支持ManyToManyField字段,因为这将需要为表中的每一行执行单独的SQL语句。 如果您想要这样做,请为您的模型提供自定义方法,并将该方法的名称添加到list_display。 (有关list_display中自定义方法的更多信息,请参阅下文。)

  • 如果该字段是BooleanField或NullBooleanField,Django将显示一个漂亮的“开”或“关”图标而不是True或False。

  • 如果给定的字符串是模型,ModelAdmin或可调用的方法,Django将默认HTML转义输出。 要转义用户输入并允许自己的非转义标记,请使用format_html()。

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

from django.contrib import admin
from django.db import models
from django.utils.html import format_html

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    color_code = models.CharField(max_length=6)

    def colored_name(self):
        return format_html(
            '<span style="color: #{};">{} {}</span>',
            self.color_code,
            self.first_name,
            self.last_name,
        )

class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'colored_name')
  • 正如一些示例已经演示的那样,当使用可调用,模型方法或ModelAdmin方法时,您可以通过向可调用对象添加short_description属性来自定义列的标题。

  • 如果字段的值为None,空字符串或不带元素的iterable,则Django将显示 - (破折号)。 您可以使用AdminSite.empty_value_display覆盖它:

from django.contrib import admin

admin.site.empty_value_display = '(None)'

您还可以使用ModelAdmin.empty_value_display:

class PersonAdmin(admin.ModelAdmin):
    empty_value_display = 'unknown'

或者在字段级别:

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

    def birth_date_view(self, obj):
         return obj.birth_date

    birth_date_view.empty_value_display = 'unknown'

如果给定的字符串是模型的方法,ModelAdmin或返回True或False Djallo的callable将显示一个漂亮的“on”或“off”图标,如果你给该方法一个值为True的布尔属性。

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

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

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    birthday = models.DateField()

    def born_in_fifties(self):
        return self.birthday.strftime('%Y')[:3] == '195'
    born_in_fifties.boolean = True

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

__str __()方法在list_display中与任何其他模型方法一样有效,因此完全可以这样做:

list_display = ('__str__', 'some_other_field')

通常,list_display的元素不是实际的数据库字段,不能用于排序(因为Django在数据库级别进行所有排序)。

但是,如果list_display的元素表示某个数据库字段,则可以通过设置该项的admin_order_field属性来指示此事实。

例如:

from django.contrib import admin
from django.db import models
from django.utils.html import format_html

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    color_code = models.CharField(max_length=6)

    def colored_first_name(self):
        return format_html(
            '<span style="color: #{};">{}</span>',
            self.color_code,
            self.first_name,
        )

    colored_first_name.admin_order_field = 'first_name'

class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'colored_first_name')

当尝试按照管理员中的colored_first_name排序时,上面将告诉Django按first_name字段排序。

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

colored_first_name.admin_order_field = '-first_name'

admin_order_field支持查询查找以按相关模型上的值排序。 此示例在列表显示中包含“作者名字”列,并允许按名字对其进行排序:

class Blog(models.Model):
    title = models.CharField(max_length=255)
    author = models.ForeignKey(Person, on_delete=models.CASCADE)

class BlogAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'author_first_name')

    def author_first_name(self, obj):
        return obj.author.first_name

    author_first_name.admin_order_field = 'author__first_name'

list_display的元素也可以是属性。 但请注意,由于属性在Python中的工作方式,只有在使用property()函数而不是@property装饰器时才能在属性上设置short_description。

例如:

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def my_property(self):
        return self.first_name + ' ' + self.last_name
    my_property.short_description = "Full name of the person"

    full_name = property(my_property)

class PersonAdmin(admin.ModelAdmin):
    list_display = ('full_name',)

list_display中的字段名称也将在HTML输出中显示为CSS类,每个<th>元素上的column- <field_name>形式。 例如,这可用于在CSS文件中设置列宽。

Django将尝试按此顺序解释list_display的每个元素:

  • A field of the model.
  • A callable.
  • A string representing a ModelAdmin attribute.
  • A string representing a model attribute.

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

ModelAdmin.list_display_links

使用list_display_links来控制list_display中的if和which字段是否应链接到对象的“change”页面。

默认情况下,更改列表页面会将第一列(list_display中指定的第一个字段)链接到每个项目的更改页面。 但是list_display_links让你改变这个:

  • 将其设置为无来取消链接。
  • 将其设置为要转换为链接的列的列表或字段元组(格式与list_display相同)。

您可以指定一个或多个字段。 只要字段出现在list_display中,Django就不关心链接了多少(或多少)字段。 唯一的要求是,如果要以这种方式使用list_display_links,则必须定义list_display。

在此示例中,first_name和last_name字段将在更改列表页面上链接:

class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'birthday')
    list_display_links = ('first_name', 'last_name')

在此示例中,更改列表页面网格将没有链接:

class AuditEntryAdmin(admin.ModelAdmin):
    list_display = ('timestamp', 'message')
    list_display_links = None

 

 


InlineModelAdmin对象

重写admin模板

AdminSite对象

LogEntry对象

反向解析admin的URL

staff_member_required 装饰器

猜你喜欢

转载自www.cnblogs.com/aric-zhu/p/9377013.html
今日推荐