本文是Django Admin详解系列文章的最后一篇,将重点介绍如何自定义动作(action), 如何自定义表单字段(form fields)和美化Django admin。如果你还没有阅读过前面两篇文章,建议先阅读。
Django基础(19): Django Admin管理后台详解(上)
Django基础(20): Django admin管理后台详解(中)如何自定义list_display和list_filter
谓action及如何自定义action
action即动作,是你对一个选定查询集(queryset)要进行的操作。当你选定一个查询集(queryset)后,你可以点击action下拉菜单选择action,然后点击Go对其进行批量操作(如下所示)。Django admin默认的action只有删除(delete)。
现在如果你要将文章由草案(draft)状态变为发表(published)状态,你只能一个一个地修改, 很麻烦。现在我们可以自定义一个action,实现文章状态的批量修改。代码如下所示:
#blog/admin.py
class ArticleAdmin(admin.ModelAdmin): '''设置列表可显示的字段''' list_display = ('title', 'author', 'status', 'mod_date', 'show_tags') '''自定义actions''' actions = ['make_published'] def make_published(self, request, queryset): queryset.update(status='p') make_published.short_description = "发布所选文章"
我们自定义了一个名为make_published的方法,并将其加入到了ArticleAdmin的actions属性(别忘了加引号哦)。我们还给该方法添加了一个简单描述(short_description)。现在如果你刷新页面,你就可以看到action下面多了一个"发布所选文章的"选项了。
本例中使用了queryset.update方法实现了数据批量更新, 提升了工作效率。如果你想对queryset中的对象一个一个修改或导出,你应该怎么办呢? 此时你可以遍历queryset,对单个obj逐一处理, 如下所示:
def action_func(self, request, queryset): for obj in queryset: do_something(obj)
action的权限管理
一个网站可能有多个人员有权限登录管理后台,如果每个人都有delete或导出数据的权限,是件挺可怕的事情。万一哪天某人对公司不满意清空数据或导出所有客户数据跑路呢? 所以我们必需对action也设定一定的权限。实现这个只需定义allowed_permissions属性即可。下例中要求只有change权限的管理人员才能更改文章发表状态。
make_published.allowed_permissions = ('change',)
下例中我们重写了get_actions方法,只给了用户名为John批量删除对象的权限。如果用户名不为John,我们把delete_selected动作从下拉菜单中删除。
class ArticleAdmin(admin.ModelAdmin): def get_actions(self, request): actions = super().get_actions(request) if request.use.username != 'John': if 'delete_selected' in actions: del actions['delete_selected'] return actions
自定义显示表单
如果我们想实现根据不同的用户显示不同表单form,我们可以通过重写get_form方法实现。如下例中给Superuser显示了不同的表单。
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)
自定义显示表单的ForeinKey字段
django admin对于一个字段默认会显示所有的ForeignKey(比如文章类别)。下利中通过重写formfiled_for_foreignkey方法可只显示用户自己创建的文章类别。
class MyModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "cateogry": kwargs["queryset"] = Category.objects.filter(owner=request.user) return super().formfield_for_foreignkey(db_field, request, **kwargs)
自定义显示表单的多对多字段
通过重写formfiled_for_manytomany方法可只显示用户自己创建的多对多字段。
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)
自定义显示表单的Choice字段
下例中通过重写formfiled_for_choice_field方法给superuser多了一个选择。
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)
自定义搜索选项search_field
如果你定义了搜索选项search_field, django admin上就会出现一个搜索框,允许你按定义的字段快速搜索一个对象。注意search_field只能用于CharField或TextField。
search_fields = ['title', 'user__email'] # 按文章title和用户email搜索 search_fields = ['user__first_name'] # 按用户first name模糊查询icontains search_fields = ['user__first_name__iexact'] # 按用户first name精确匹配
如何美化Django的admin
如果你不使用第三方的库如django-xadmin, 你唯一能够美化django admin的方法就是覆盖它本来的模板。默认的django模板是放在contrib/admin/templates/admin目录下的。django的模板美化可以针对某个项目(project), 某个应用(app)或某个模型(model)来进行,提供了非常大的灵活度。
1. 针对项目(project)全站美化。
按如下顺序新建目录,拷入新的模板修改即可。
my_project/templates/admin/
2. 针对应用(app)美化。
按如下顺序新建目录,拷入新的模板修改即可。
my_project/templates/admin/my_app
2. 针对模型(model)美化。
按如下顺序新建目录,放入新的模板即可。
my_project/templates/admin/my_app/model_name
小结
本文总结了如何自定义action并对action设定权限,还详细分析了如何自定义显示表单及美化django admin。接下来我们继续会用Django开发些有趣的项目,欢迎关注。
非广告: 今天双11,阿里云百度云腾讯云都在打折,建议大家去申请个1核2G的云服务器(centos或ubuntu版的)学习练手,才100-200元/年,非常值得投入。小编我后续讲解django项目部署时会用到。
大江狗
2018.11.11