1. ModelAdmin 属性

  1. class AuthorAdmin(admin.ModelAdmin):
  2. list_display = ('name', 'age')
  3. # 中的 list_display 就是一个属性

ModelAdmin 中内置了许多可以用来定义 admin 界面和功能的属性。

因为模型管理器(比如:AuthorAdmin)都是 ModelAdmin 的子类,所以可以直接属性。

2. 【速查】

2.1. [ 列表页 ]

属性 描述 类型 默认值
Actions -
actions 自定义 actions 的列表 list
actions_on_top 是否显示 actions 下拉框(在数据列表上方) Boolean True
actions_on_bottom 同上(在列表下方) Boolean False
actions_selection_counter 是否显示选中对象数量(actions 右侧) Boolean True
列表加载 -
list_display 按希望顺序显示指定字段 tuple
list_display_links 指定链接到修改页面的字段 tuple
list_editable 在列表中可以编辑的字段(可修改后直接批量保存) tuple
list_max_show_all 可以显示 show all 的最大列表行数 int 200
list_per_page 每页显示行数 int 100
list_select_related 相关项缓存(减少数据库访问) Boolean/list/tuple False
empty_value_display 空白显示的内容 string
show_full_result_count 是否显示过滤后的对象总数信息 Boolean True
过滤和搜索 -
search_fields 搜索框 list
list_filter 激活列表页侧边栏过滤(右侧) tuple
preserve_filters 修改后过滤器是否返回原来状态 Boolean True
其他 -
ordering 排序方式 tuple/list
date_hierarchy 根据指定日期字段,创建时间导航栏 string
filter_horizontal 水平扩展多对多字段
filter_vertical 同上,垂直
view_on_site 是否开启顶部 View site 链接

2.2. [ 编辑页 ]

属性 描述 类型 默认值
字段 -
fields 按希望顺序显示指定字段(编辑页) tuple
exclude 不显示的字段 tuple
readonly_fields 不可编辑字段
表单 -
form 编写自定义的 ModelForm 代替Dj默认创建的 tuple
formfield_overides 替换原有空间 dict
fieldsets 分组显示字段 tuple
radio_fields 使用 radio_box 展示的字段(编辑页面)【仅限 choices 集合和 ForeignKey 字段】 dict
raw_id_fields 改变外键/多对多展示方式(输入框,右边带放大镜,点击进入选择) tuple
保存 -
save_as 保存新对象方式 Boolean False
save_as_continue 保存新对象后跳转 Boolean True
save_on_top 是否开启顶部保存按钮 Boolean False

3. 属性详解

3.1. actions 自定义 actions 的列表

list

3.1.1. 例子:批量更新

将选择的文章由“草稿”状态更新为“发布”状态。

  1. # models.py
  2. STATUS_CHOICES = (
  3. ('d', 'Draft'),
  4. ('p', 'Published'),
  5. ('w', 'Withdrawn'),
  6. )
  7. class Article(models.Model):
  8. title = models.CharField(max_length=100)
  9. body = models.TextField()
  10. status = models.CharField(max_length=1, choices=STATUS_CHOICES)
  11. def __str__(self):
  12. return self.title
  13. # admin.py
  14. class ArticleAdmin(admin.ModelAdmin):
  15. list_display = ['title', 'status']
  16. ordering = ['title']
  17. # 3:添加 actions
  18. actions = ['make_published']
  19. # 1:设置操作函数
  20. def make_published(self, request, queryset):
  21. # 这里使用了 queryset 自带的 update() 批量更新
  22. queryset.update(status='p')
  23. # 大多情况下需要:
  24. for obj in queryset:
  25. do_something_with(obj)
  26. # 提示消息:
  27. if rows_updated == 1:
  28. message_bit = "1篇文章"
  29. else:
  30. message_bit = "%s 篇文章" % rows_updated
  31. self.message_user(request, "%s 成功更新为已发布" % message_bit)
  32. # 2:设置显示描述(代替函数名)
  33. make_published.short_description = "将所选文章设置为已发布"

3.1.2. 全局 Actions

  1. def export_selected_objects(modeladmin, request, queryset):
  2. #...
  3. admin.site.add_action(export_selected_objects)

3.1.3. 禁用 Actions

3.1.3.1. 全站禁用

  1. # 全站禁用内置删除
  2. admin.site.disable_action('delete_selected')
  3. # 虽然禁用,但可以单独启用
  4. class MyModelAdmin(admin.ModelAdmin):
  5. actions = ['delete_selected', 'a_third_action']

3.1.3.2. 模型中禁用所有

  1. class MyModelAdmin(admin.ModelAdmin):
  2. actions = None

3.1.3.3. 按条件禁用

  1. # 比如:允许用户名以“J”开头的用户批量删除对象,但其它用户不行
  2. class MyModelAdmin(admin.ModelAdmin):
  3. #...
  4. def get_actions(self, request):
  5. actions = super(MyModelAdmin, self).get_actions(request)
  6. if request.user.username[0].upper() = 'J':
  7. if 'delete_selected' in actions:
  8. del actions['delete_selected']
  9. return actions

3.2. list_display 按希望顺序显示指定字段(列表页)

tuple

3.2.1. 前端自定义

list_display中的字段名会自动生成CSS class,在 <th> 中以 column-<field_name> 的格式。

3.2.2. 示例

不设置时,默认显示 __str___() 返回的内容

可以设置四种类型的值

3.2.2.1. 模型字段名

  1. list_display = ('first_name', 'last_name')

3.2.2.2. 接收模型实例为参数的函数

  1. def upper_case_name(obj):
  2. return ("%s %s" % (obj.first_name, obj.last_name)).upper()
  3. upper_case_name.short_description = 'Name'
  4. class PersonAdmin(admin.ModelAdmin):
  5. list_display = (upper_case_name,)

3.2.2.3. 表示 ModelAdmin 属性的字符串(上面2换种写法)

  1. class PersonAdmin(admin.ModelAdmin):
  2. list_display = ('upper_case_name',)
  3. def upper_case_name(self, obj):
  4. return ("%s %s" % (obj.first_name, obj.last_name)).upper()
  5. upper_case_name.short_description = 'Name'

3.2.2.4. self 模型实例

  1. # models.py
  2. class Person(models.Model):
  3. name = models.CharField(max_length=50)
  4. birthday = models.DateField()
  5. def decade_born_in(self):
  6. return self.birthday.strftime('%Y')[:3] + "0's"
  7. decade_born_in.short_description = 'Birth decade'
  8. # admin.py
  9. class PersonAdmin(admin.ModelAdmin):
  10. list_display = ('name', 'decade_born_in')

注意

  1. ForeignKey:显示 __str__() 的值
  2. BooleanField / NullBooleanField:会用 on/off 图标代替 True/False(例子)
  3. 如果值是模型、ModelAdmin、方法:默认会对返回结果进行HTML转义(例子)
  4. 不支持多对多字段
  5. 如果其中元素不是某个具体字段:默认不能排序,要排序需要添加 admin_order_field 属性(例子)
  6. Short Description 只能给属性函数添加(例子)

3.3. list_display_links 指定链接到修改页面的字段

tuple

不设置这个属性时,Django 默认第一个元素为可跳转链接。这个属性可以修改默认设置。

比如

  1. list_display = ('first_name', 'last_name', 'birthday')
  2. list_display_links = ('first_name', 'last_name')

以下无法跳转(设置为 None)

  1. list_display = ('timestamp', 'message')
  2. list_display_links = None

注意

  1. 设置为 None:无法跳转
  2. 必须先设置好了 list_display

3.4. list_editable 在列表中可以编辑的字段(可修改后直接批量保存)

tuple

  1. list_editable = ('last_name',)

注意

  1. 只能设置 list_display 中的元素
  2. 不能设置 list_display_links 中的元素

3.5. list_select_related 相关项缓存(减少数据库访问)

Boolean/list/tuple

默认 False

False时,Dj会对将 ForeignKey 调用 select_related()

  1. list_select_related = ('author', 'category')

3.6. empty_value_display 空白时显示的内容

string

默认显示 “ - “

3.6.1. 整个类管理中设置

  1. class PersonAdmin(admin.ModelAdmin):
  2. empty_value_display = 'unknown'
  3. # 在类中,没有内容的字段格子显示 unknown

3.6.2. 只在某个字段设置

  1. class AuthorAdmin(admin.ModelAdmin):
  2. fields = ('name', 'title', 'view_birth_date')
  3. def view_birth_date(self, obj):
  4. return obj.birth_date
  5. # 注意下面这句
  6. view_birth_date.empty_value_display = '???'

3.6.3. 全局设置

  1. from django.contrib import admin
  2. admin.site.empty_value_display = '(None)'

3.7. show_full_result_count 是否显示过滤后的对象总数信息

Boolean

默认为True

默认时显示 99 results (103 total),表很大时会耗费一定时间和资源。设为 False,显示 99 results (Show all)

3.8. search_fields 搜索框

list

3.8.1. 示例

  1. # 比如模型有个外键时 user,根据 user 的 email 字段查找
  2. search_fields = ['user__email']

3.8.2. 对比

比如,如果搜索 John Lennon

相当于 SQL
['first_name', 'last_name'] WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
['^first_name','^last_name'] WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
['=first_name','=last_name'] WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')

3.9. list_filter 激活列表页侧边栏过滤(右侧)

tuple/list

字段类型必须是 BooleanField、CharField、DateField、DateTimeField、IntegerField、ForeignKey、ManyToManyField 之一

3.9.1. 示例

  1. list_filter = ('is_staff', 'company')
  2. # 跨表关联
  3. list_filter = ('company__name',)

3.9.2. 重写 lookups 和 queryset 方法

  1. from datetime import date
  2. from django.contrib import admin
  3. from django.utils.translation import ugettext_lazy as _
  4. class DecadeBornListFilter(admin.SimpleListFilter):
  5. # 提供一个可读的标题
  6. title = _('出生年代')
  7. # 用于URL查询的参数.
  8. parameter_name = 'decade'
  9. def lookups(self, request, model_admin):
  10. """
  11. 返回一个二维元组。每个元组的第一个元素是用于URL查询的真实值,
  12. 这个值会被self.value()方法获取,并作为queryset方法的选择条件。
  13. 第二个元素则是可读的显示在admin页面右边侧栏的过滤选项。
  14. """
  15. return (
  16. ('80s', _('80年代')),
  17. ('90s', _('90年代')),
  18. )
  19. def queryset(self, request, queryset):
  20. """
  21. 根据self.value()方法获取的条件值的不同执行具体的查询操作。
  22. 并返回相应的结果。
  23. """
  24. if self.value() == '80s':
  25. return queryset.filter(birthday__gte=date(1980, 1, 1),
  26. birthday__lte=date(1989, 12, 31))
  27. if self.value() == '90s':
  28. return queryset.filter(birthday__gte=date(1990, 1, 1),
  29. birthday__lte=date(1999, 12, 31))
  30. class PersonAdmin(admin.ModelAdmin):
  31. list_display = ('first_name', 'last_name', "colored_first_name",'birthday')
  32. list_filter = (DecadeBornListFilter,)

3.10. preserve_filters 修改后过滤器是否返回原来状态

Boolean

默认 True

True:进行创建、删改后,页面保持原有过滤状态
False:进行上述操作时,返回未过滤状态

3.11. ordering 排序方式

tuple/list

动态排序需要自己实现 get_ordering()

3.12. date_hierarchy 根据指定日期字段,创建时间导航栏

string

  1. date_hierarchy = 'pub_date'
  2. # 通过 pub_date 过滤对象

3.13. view_on_site 是否开启顶部 View site 链接

Mix

3.13.1. 关闭 View site

  1. # 关闭在 Person 模型管理时顶部的 View site
  2. class PersonAdmin(admin.ModelAdmin):
  3. view_on_site = False

3.13.2. 自定义 View site

  1. # 自定义 Person 模型管理时顶部的 View site
  2. from django.urls import reverse
  3. class PersonAdmin(admin.ModelAdmin):
  4. def view_on_site(self, obj):
  5. url = reverse('person-detail', kwargs={'slug': obj.slug})
  6. return 'https://example.com' + url

3.14. fields 按希望顺序显示指定字段(编辑页)

tuple

  1. fields = (('url','title'), 'content')
  2. # url 和 title 显示在一行
  3. # 默认显示所有 AutoField 和 editable=True 的字段

3.15. exclude 不显示的字段

tuple

  1. # 比如有三个字段 name, title, birth_date
  2. fields = ('name', 'title')
  3. # 效果与下面相同(一个元素必须加,)
  4. exclude = ('birth_date',)

3.16. readonly_fields 不可编辑字段

  1. readonly_fields = ('addr',)

3.17. formfield_overides 替换原有空间

dict

  1. # 比如:用自己写的 RichTextEditorWidget(富文本控件),来代替传统的 <textarea>(文本域控件)
  2. # 从对应的目录导入我们先前写好的widget和model
  3. from myapp.widgets import RichTextEditorWidget
  4. from myapp.models import MyModel
  5. class MyModelAdmin(admin.ModelAdmin):
  6. formfield_overrides = {
  7. models.TextField: {'widget': RichTextEditorWidget},
  8. }

3.18. fieldsets 分组显示字段

tuple

3.18.1. 示例

格式为: (分组标题字符串, field_options 字典)

  1. fieldsets = (
  2. (None, {
  3. 'fields': ('url', 'title', 'content', 'sites')
  4. }),
  5. ('Advanced options', {
  6. 'classes': ('collapse',), # 折叠
  7. 'fields': ('registration_required', 'template_name'),
  8. }),
  9. )

3.18.2. field_options 字典

字典键 必填 描述 例子
fields Yes 要在该分组显示的字段 {'fields': ('first_name', 'last_name', 'address', 'city', 'state'),} # () 使显示在一行
{'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),} # 可以包含 readonly_fields 作为只读字段 ???
classes No 分组的CSS类 {'classes': ('wide', 'collaspe'),}
# wide 更宽的水平空间
# collaspe 折叠
description No 可选说明文本(分组顶部) 需要使用 django.utils.html.escape() 转义

3.19. radio_fields 使用 radio_box 展示的字段(编辑页面)【仅限 choices 集合和 ForeignKey 字段】

dict

  1. class PersonAdmin(admin.ModelAdmin):
  2. # Group 字段垂直布局(水平布局 HORIZONTAL)
  3. radio_fields = {"group": admin.VERTICAL}

3.20. raw_id_fields 改变外键/多对多展示方式(输入框,右边带放大镜,点击进入选择)

tuple

raw_id_fields = (groups)

3.21. save_as 保存新对象方式

Boolean

默认 False

默认右下角“Save and add another”;如果 True,右下角“Save as new”

3.22. save_as_continue 保存新对象后跳转

Boolean

默认 True

默认跳转到对象修改页面,设为 False,跳转到元素列表页面