通常情况下,admin的工作模式是“选中目标,然后修改目标”,但在同时修改大量目标的时候,这种模式就变得重复、繁琐。

为此,admin提供了自定义功能函数actions的手段,可以批量对数据进行修改。admin内置了一个批量删除对象的操作,如下图所示:

下面以一个新闻应用的文章模型为例,介绍一个批量更新的自定义actions,它将选择的文章由“草稿”状态更新为“发布”状态:

首先是模型的代码:

  1. from django.db import models
  2.  
  3. STATUS_CHOICES = (
  4. ('d', 'Draft'),
  5. ('p', 'Published'),
  6. ('w', 'Withdrawn'),
  7. )
  8.  
  9. class Article(models.Model):
  10. title = models.CharField(max_length=100)
  11. body = models.TextField()
  12. status = models.CharField(max_length=1, choices=STATUS_CHOICES)
  13.  
  14. def __str__(self): # __unicode__ on Python 2
  15. return self.title

一、编写action

action必须携带三个参数:

  • 当前的ModelAdmin
  • 当前的HttpRequest对象(即request)
  • 被选择的对象(即QuerySet)

在应用中的admin.py文件中写入:

  1. def make_published(modeladmin, request, queryset):
  2. queryset.update(status='p')

注意:这里我们作为例子,简单地使用了queryset自带的update()方法,它能批量操作。但在多数情况下,你要自己遍历queryset的每个元素,并编写具体的操作。也就是:

  1. for obj in queryset:
  2. do_something_with(obj)

还可以设置一个简单易懂的简短描述(可以使用中文),用于代替生硬的函数名:

  1. def make_published(modeladmin, request, queryset):
  2. queryset.update(status='p')
  3. # 注意缩进,下面这句不在函数体内。
  4. make_published.short_description = "Mark selected stories as published"

二、将自定义action添加到对应的ModelAdmin中

关键是其中的actions = [make_published]这句。

  1. from django.contrib import admin
  2. from myapp.models import Article
  3.  
  4. def make_published(modeladmin, request, queryset):
  5. queryset.update(status='p')
  6. make_published.short_description = "Mark selected stories as published"
  7.  
  8. class ArticleAdmin(admin.ModelAdmin):
  9. list_display = ['title', 'status']
  10. ordering = ['title']
  11. actions = [make_published]
  12.  
  13. admin.site.register(Article, ArticleAdmin)

然后,页面看起来是下面的样子(注意下拉框):

处理错误

这其中,如果你能够预知在自定义的操作中可能产生的错误,请处理该错误,并通过django.contrib.admin.ModelAdmin.message_user()以友好的方式给予用户提示信息。

三、将action定义为ModelAdmin的方法

上面的make_published看起来已经不错了,但是我们一般会将它作为ModelAdmin的方法来使用。下面我们把它移到ArticleAdmin类中:

  1. class ArticleAdmin(admin.ModelAdmin):
  2. ...
  3.  
  4. actions = ['make_published'] # 请注意这里改成字符串引用了
  5. # 第一个参数变为self
  6. def make_published(self, request, queryset):
  7. queryset.update(status='p')
  8. make_published.short_description = "Mark selected stories as published"

这样做的好处是自定义方法可以直接访问类本身。例如下面使用self引用,为方法添加提示信息的功能:

  1. class ArticleAdmin(admin.ModelAdmin):
  2. ...
  3.  
  4. def make_published(self, request, queryset):
  5. rows_updated = queryset.update(status='p')
  6. if rows_updated == 1:
  7. message_bit = "1 story was"
  8. else:
  9. message_bit = "%s stories were" % rows_updated
  10. self.message_user(request, "%s successfully marked as published." % message_bit)

回到浏览器,再试试,你会看到如下图所示(注意顶部的绿色提示行):

四、跳转到中间页面

默认情况下,执行完actions后,浏览器会返回先前的修改列表页面。但有时候,一些复杂的action需要返回中间页面,例如内置的删除方法,在执行删除动作之前,会弹出一个删除确认页面。

要实现这个功能,只需要在action方法中返回一个HttpResponse(或它的子类)。 例如下面是一个利用Django内置的序列化函数将一个对象保存为json格式的范例:

  1. from django.http import HttpResponse
  2. from django.core import serializers
  3.  
  4. def export_as_json(modeladmin, request, queryset):
  5. response = HttpResponse(content_type="application/json")
  6. serializers.serialize("json", queryset, stream=response)
  7. return response

多数情况下,我们会使用HttpResponseRedirect跳转到一个中间页面,并在GET方法的url中携带别选择的对象作为参数传递过去,然后在这个新的视图中接收这个参数,并编写具体的更加复杂的业务逻辑,如下面的代码所示:

  1. from django.contrib import admin
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.http import HttpResponseRedirect
  4.  
  5. def export_selected_objects(modeladmin, request, queryset):
  6. # 获得被打钩的checkbox对应的对象
  7. selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
  8. # 获取对应的模型
  9. ct = ContentType.objects.get_for_model(queryset.model)
  10. # 构造访问的url,使用GET方法,跳转到相应的页面
  11. return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected)))

具体的业务views这里没有给出,作为练习,留给大家。

五、编写可用于整个admin站点的action

前面创建的actions智能应用于绑定的模型。实际上有时候,我们还需要可以对admin站点内所有模型都有效的acitons。上面写的export_selected_objects函数可以是一个很好的例子。要实现这一功能,你需要使用内置的AdminSite.add_action方法:

AdminSite.add_action(action, name=None)[source]

  1. from django.contrib import admin
  2.  
  3. admin.site.add_action(export_selected_objects)

六、禁用acitons

有时候,对于某些actions,我们想全局禁用或者局部禁用它。需要使用AdminSite.disable_action(name)方法。

  • 禁用全站级别的acitons:

例如,禁用内置的删除方法:

  1. admin.site.disable_action('delete_selected')
  • 全站禁用,但个别可用:在ModelAdmin.actions中显式地引用。

例如:

  1. # 全站禁用删除功能
  2. admin.site.disable_action('delete_selected')
  3.  
  4. # 这个老老实实的被禁了
  5. class SomeModelAdmin(admin.ModelAdmin):
  6. actions = ['some_other_action']
  7. ...
  8.  
  9. # 这个声明:我还要用
  10. class AnotherModelAdmin(admin.ModelAdmin):
  11. actions = ['delete_selected', 'a_third_action']
  12. ...
  • 在指定模型中禁用所有actions:设置ModelAdmin.actions为None。(这会连带全局actions一起禁用了。)
  1. class MyModelAdmin(admin.ModelAdmin):
  2. actions = None
  • 根据条件自动启用或禁用:

还可以根据条件自动选择性的启动或禁用某些acitons,你只需要改写ModelAdmin.get_actions()方法。

该方法将返回一个包含actions的字典。字典的键是aciton的名字(也就是前面的'delete_selected', 'a_third_action'之类),值是一个元组,包含(函数、名字、别名)

例如,允许用户名以“J”开头的用户批量删除对象,但其它用户不行:

  1. class MyModelAdmin(admin.ModelAdmin):
  2. ...
  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

django自定义Admin actions的更多相关文章

  1. 第五章:Admin管理后台 - 2:自定义Admin actions

    通常情况下,admin的工作模式是"选中目标,然后修改目标",但在同时修改大量目标的时候,这种模式就变得重复.繁琐. 为此,admin提供了自定义功能函数actions的手段,可以 ...

  2. Django 自定义 admin

    为 model 自定义显示 label是这个Field如果在form中的话会显示的.而verbose_name在form中不会显示.只是作为一种说明而已 callable()   -->  是否 ...

  3. Part 7:自定义admin站点--Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  4. 自定义django的admin后台action

    django的admin后台管理系统中自带了一个批量删除所选对象的action. 我们还可以添加自定义的action来实现其它类似的功能,如批量修改某个字段的功能.简单的,例如将文章批量标记为已发布的 ...

  5. 自定义Django的admin界面

    第6章介绍了Django的admin界面,现在是回过头来仔细看看这个的时候了 我们前面讲的几次admin是Django的"杀手级特性",并且大多数Django开发人员很快爱上了它节 ...

  6. Django---ORM的常用字段和自定义字段,DjangoORM字段与数据库类型对应,字段参数和Meta的参数,Django的admin操作,13中orm操作方法,单标的双下方法

    Django---ORM的常用字段和自定义字段,DjangoORM字段与数据库类型对应,字段参数和Meta的参数,Django的admin操作,13中orm操作方法,单标的双下方法 一丶ORM常用字段 ...

  7. Django 中自定义 Admin 样式与功能

    目录 自定义 Admin 样式与功能 1 页面修改中文 1.1 语言设置为中文 1.2 应用管理设置为中文 1.3 数据库表设置为中文 1.4 数据库表字段名称修改为中文 2 修改后台样式 2.1 安 ...

  8. Django 在admin中自定义app名

    前提条件,注册时是: 完整的注册,不是直接用app名进行注册 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'dj ...

  9. 第一个Django应用 - 第七部分:自定义admin

    Django的admin站点是自动生成的.高度可定制的,它是Django相较其它Web框架独有的内容,广受欢迎.如果你觉得它不够美观,还有第三方美化版xadmin.请一定不要忽略它,相信我,它值得拥有 ...

随机推荐

  1. Kattis之旅——Number Sets

    You start with a sequence of consecutive integers. You want to group them into sets. You are given t ...

  2. 【web前端】移动端控制台插件,手机端页面查看相关页面控制台信息

    一般调试手机端页面时,基本是在PC端使用手机模式进行断点或console调试.或查看有用的控制台信息的,但依旧有部分功能无法在PC端调试,经常需要使用alert进行断点,然后在手机端看效果,但是这样并 ...

  3. JDBC和servlet设计思路、DAO模式思路、MVC思路粗略总结

    #JDBC和Servlet联合起来使用的项目思路: 说明:建库,最好一开始设置utf8字符集 step1: 在数据库中建表 如   create table t_user{ ...... } step ...

  4. Fiddler(三)Fiddler设置手机抓包

    一.前提 我们要实现手机抓包,必须要手机连接的wifi和PC段连接的wifi所处同一个局域网内,如果你使用的是笔记本,那么这个就好办了,如果你使用的是台式机,那么你还需要准备一个无线网卡.我使用的是F ...

  5. webstorm 安装与基本使用

    1.1 webstorm 安装与配置 1.安装: https://blog.csdn.net/jiangxinyu50/article/details/79104016 2.使用: https://w ...

  6. Android之扫描文件或文件夹

    我们或许经常会遇到这种情况,明明保存了图片,但是当你打开图片时,却没有找到这张图片,手机重启之后才能看到.这是因为SD卡并没有重新挂载,图库也无法把这张图片加载进去,解决这个问题非常简单,只需要我们重 ...

  7. Codeforces 834D The Bakery - 动态规划 - 线段树

    Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredient ...

  8. MySql 语句收集

    目录 =与:=区别 序列号: 分组: 子查询分组: 同数据库表数据迁移 存储过程 参考: =与:=区别 = 只有在set和update时才是和:=一样,赋值的作用,其它都是等于的作用.鉴于此,用变量实 ...

  9. oracle单行函数 之 时间函数

    select  systemdate from dual --得到时间 select systemdate+300 from dual  --日期 +数字=日期,表示若干天之后的日期 select s ...

  10. p3168 [CQOI2015]任务查询系统(差分+主席树)

    恕我才学浅薄,一开始想到的是树状数组+线段树,然后看了题解才第一次见到了差分这种神奇的科技 仔细想想,主席树的本质不就是前缀和嘛,加上一个差分也是可以的,没想到真是罪过罪过 对时间维护一个差分 在Si ...