《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情

自定义后台管理

阅读:378166890    分享到

Django 后台管理系统不但简单易用,而且还可以高度定制化,这样,我们就可以扩展丰富的功能,本节课,我们就来学习如何对 Django 后台管理系统进行自定义。

自定义字段标签

在编辑页面中,每个字段的标签都是从模块的字段名称生成的。规则很简单:用空格替换下划线;首字母大写。例如: Book 模块中 publication_date 的标签是 Publication date。

然而,字段名称并不总是贴切的。有些情况下,你可能想自定义一个标签。你只需在模块中指定 verbose_name

举个例子,说明如何将 Author.email 的标签改为 e-mail,中间有个横线。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, **verbose_name='e-mail'** )

修改后重启服务器,你会在 author 编辑页面中看到这个新标签。

请注意,你不必把 verbose_name 的首字母大写,除非是连续大写(如:"USA state")。Django 会自动适时将首字母大写,并且在其它不需要大写的地方使用 verbose_name 的精确值。

最后还需注意的是,为了使语法简洁,你可以把它当作固定位置的参数传递。这个例子与上面那个的效果相同。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(**'e-mail',**  blank=True)

但这不适用于 ManyToManyFieldForeignKey 字段,因为它们第一个参数必须是模块类。 那种情形,必须显式使用 verbose_name 这个参数名称。

自定义列表

迄今为止,我们做的 blank=Truenull=Trueverbose_name 修改其实是模块级别,而不是管理级别的。也就是说,这些修改实质上是构成模块的一部分,并且正好被管理工具使用,而不是专门针对管理工具的。

除了这些,Django 还提供了大量选项让你针对特别的模块自定义管理工具。这些选项都在 ModelAdmin classes 里面,这些类包含了管理工具中针对特别模块的配置。

让我们更深一步:自定义 Author 模块的列表中的显示字段。列表默认地显示查询结果中对象的 unicode()。在第五章中,我们定义 Author 对象的 unicode() 方法,用以同时显示作者的姓和名。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail')

    **def __str__(self):**
        **return '%s %s' % (self.first_name, self.last_name)**

结果正如下图所示,列表中显示的是每个作者的姓名。

我们可以在这基础上改进,添加其它字段,从而改变列表的显示。这个页面应该提供便利,比如说:在这个列表中可以看到作者的邮箱地址。如果能按照姓氏或名字来排序,那就更好了。

为了达到这个目的,我们将为Author模块定义一个ModelAdmin类。 这个类是自定义管理工具的关键,其中最基本的一件事情是允许你指定列表中的字段。 打开admin.py并修改:

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

**class AuthorAdmin(admin.ModelAdmin):**
    **list_display = ('first_name', 'last_name', 'email')**

admin.site.register(Publisher)
**admin.site.register(Author, AuthorAdmin)**
admin.site.register(Book)

解释一下代码:

我们新建了一个类AuthorAdmin,它是从django.contrib.admin.ModelAdmin派生出来的子类,保存着一个类的自定义配置,以供管理工具使用。 我们只自定义了一项:list_display, 它是一个字段名称的元组,用于列表显示。 当然,这些字段名称必须是模块中有的。我们修改了admin.site.register()调用,在Author后面添加了AuthorAdmin。你可以这样理解: 用AuthorAdmin选项注册Author模块。admin.site.register()函数接受一个ModelAdmin子类作为第二个参数。 如果你忽略第二个参数,Django将使用默认的选项。PublisherBook的注册就属于这种情况。

弄好了这个东东,再刷新author列表页面,你会看到列表中有三列:姓氏、名字和邮箱地址。另外,点击每个列的列头可以对那列进行排序。

接下来,让我们添加一个快速查询栏。向AuthorAdmin追加search_fields,如:

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email')
        **search_fields = ('first_name', 'last_name')**

刷新浏览器,你会在页面顶端看到一个查询栏。我们刚才所作的修改列表页面,添加了一个根据姓名查询的查询框。正如用户所希望的那样,它是大小写敏感,并且对两个字段检索的查询框。如果查询 "bar",那么名字中含有 Barney 和姓氏中含有 Hobarson 的作者记录将被检索出来。

接下来,让我们为 Book 列表页添加一些过滤器。

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email')
    search_fields = ('first_name', 'last_name')

**class BookAdmin(admin.ModelAdmin):**
    **list_display = ('title', 'publisher', 'publication_date')**
    **list_filter = ('publication_date',)**

admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
**admin.site.register(Book, BookAdmin)**

由于我们要处理一系列选项,因此我们创建了一个单独的 ModelAdmin 类:BookAdmin。首先,我们定义一个 list_display,以使得页面好看些。 然后,我们用 list_filter 这个字段元组创建过滤器,它位于列表页面的右边。Django 为日期型字段提供了快捷过滤方式,它包含:今天、过往七天、当月和今年。这些是开发人员经常用到的。下图显示了修改后的页面。

过滤器 同样适用于其它类型的字段,而不单是 日期型 (请在布尔型外键 字段上试试)。当有两个以上值时,过滤器就会显示。

另外一种过滤日期的方式是使用 date_hierarchy 选项,如:

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    **date_hierarchy = 'publication_date'**

修改好后,页面中的列表顶端会有一个逐层深入的导航条,效果如下图。它从可用的年份开始,然后逐层细分到月乃至日。

请注意,date hierarchy 接受的是 字符串_ ,而不是元组。因为只能对一个日期型字段进行层次划分。

最后,让我们改变默认的排序方式,按publication date降序排列。列表页面默认按照模块 class Meta(详见第五章)中的 ordering 所指的列排序。但目前没有指定 ordering值,所以当前排序是没有定义的。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    **ordering = ('-publication_date',)**

这个ordering选项基本像模块中class Metaordering那样工作,除了它只用列表中的第一个字段名。 如果要实现降序,仅需在传入的列表或元组的字段前加上一个减号(-)。

刷新 book 列表页面观看实际效果。注意 Publication date 列头现在有一个小箭头显示排序。

我们已经学习了主要的选项。 通过使用它们,你可以仅需几行代码就能创建一个功能强大、随时上线的数据编辑界面。

自定义编辑表单

正如自定义列表那样,编辑表单多方面也能自定义。

首先,我们先自定义字段顺序。 默认地,表单中的字段顺序是与模块中定义是一致的。我们可以通过使用 ModelAdmin 子类中的 fields 选项来改变它:

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **fields = ('title', 'authors', 'publisher', 'publication_date')**

完成之后,编辑表单将按照指定的顺序显示各字段。它看起来自然多了——作者排在书名之后。字段顺序当然是与数据条目录入顺序有关,每个表单都不一样。

通过fields这个选项,你可以排除一些不想被其他人编辑的fields 只要不选上不想被编辑的 field(s) 即可。 当你的 admin 用户只是被信任可以更改你的某一部分数据时,或者,你的数据被一些外部的程序自动处理而改变了了,你就可以用这个功能。例如,在 book 数据库中,我们可以隐藏 publication_date,以防止它被编辑。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **fields = ('title', 'authors', 'publisher')**

这样,在编辑页面就无法对 publication date 进行改动。如果你是一个编辑,不希望作者推迟出版日期的话,这个功能就很有用。(当然,这纯粹是一个假设的例子。)

当一个用户用这个不包含完整信息的表单添加一本新书时,Django 会简单地将 publication_date 设置为 None,以确保这个字段满足 null=True 的条件。

另一个常用的编辑页面自定义是针对多对多字段的。真如我们在 book 编辑页面看到的那样,多对多字段 被展现成多选框。虽然多选框在逻辑上是最适合的HTML控件,但它却不那么好用。 如果你想选择多项,你必须还要按下 Ctrl 键(苹果机是 command 键)。 虽然管理工具因此添加了注释(help_text),但是当它有几百个选项时,它依然显得笨拙。

更好的办法是使用 filter_horizontal。让我们把它添加到 BookAdmin 中,然后看看它的效果。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **filter_horizontal = ('authors',)**

(如果你一着跟着做练习,请注意移除 fields 选项,以使得编辑页面包含所有字段。)

刷新 book 编辑页面,你会看到 Author 区中有一个精巧的 JavaScript 过滤器,它允许你检索选项,然后将选中的 authors 从 Available 框移到 Chosen 框,还可以移回来。

我们强烈建议针对那些拥有十个以上选项的 多对多字段,使用 filter_horizontal。 这比多选框好用多了。 你可以在多个字段上使用 filter_horizontal,只需在这个元组中指定每个字段的名字。

ModelAdmin 类还支持 filter_vertical 选项。它像 filter_horizontal 那样工作,除了控件都是垂直排列,而不是水平排列的。至于使用哪个,只是个人喜好问题。

filter_horizontalfilter_vertical 选项只能用在 多对多字段 上, 而不能用于 ForeignKey 字段。默认地,管理工具使用 下拉框 来展现 外键 字段。但是,正如 多对多字段 那样,有时候你不想忍受因装载并显示这些选项而产生的大量开销。 例如,我们的 book 数据库膨胀到拥有数千条 publishers 的记录,以致于 book 的添加页面装载时间较久,因为它必须把每一个 publishe 都装载并显示在 下拉框 中。

解决这个问题的办法是使用 raw_id_fields 选项。它是一个包含外键字段名称的元组,它包含的字段将被展现成 文本框,而不再是 下拉框

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    filter_horizontal = ('authors',)
    **raw_id_fields = ('publisher',)**

在这个输入框中,你输入什么呢? publisher 的数据库 ID 号。考虑到人们通常不会记住这些数据库 ID,管理工具提供了一个放大镜图标方便你输入。点击那个图标将会弹出一个窗口,在那里你可以选择想要添加的 publishe。


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论