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

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

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

首先是模型的代码:

  1. from django.db import models
  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): # __unicode__ on Python 2
  12. 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. def make_published(modeladmin, request, queryset):
  4. queryset.update(status='p')
  5. make_published.short_description = "Mark selected stories as published"
  6. class ArticleAdmin(admin.ModelAdmin):
  7. list_display = ['title', 'status']
  8. ordering = ['title']
  9. actions = [make_published]
  10. admin.site.register(Article, ArticleAdmin)

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

处理错误

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

三、将action定义为ModelAdmin的方法

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

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

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

  1. class ArticleAdmin(admin.ModelAdmin):
  2. ...
  3. def make_published(self, request, queryset):
  4. rows_updated = queryset.update(status='p')
  5. if rows_updated == 1:
  6. message_bit = "1 story was"
  7. else:
  8. message_bit = "%s stories were" % rows_updated
  9. 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. def export_as_json(modeladmin, request, queryset):
  4. response = HttpResponse(content_type="application/json")
  5. serializers.serialize("json", queryset, stream=response)
  6. 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. def export_selected_objects(modeladmin, request, queryset):
  5. # 获得被打钩的checkbox对应的对象
  6. selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
  7. # 获取对应的模型
  8. ct = ContentType.objects.get_for_model(queryset.model)
  9. # 构造访问的url,使用GET方法,跳转到相应的页面
  10. 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. 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. class SomeModelAdmin(admin.ModelAdmin):
  5. actions = ['some_other_action']
  6. ...
  7. # 这个声明:我还要用
  8. class AnotherModelAdmin(admin.ModelAdmin):
  9. actions = ['delete_selected', 'a_third_action']
  10. ...
  • 在指定模型中禁用所有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. def get_actions(self, request):
  4. actions = super(MyModelAdmin, self).get_actions(request)
  5. if request.user.username[0].upper() != 'J':
  6. if 'delete_selected' in actions:
  7. del actions['delete_selected']
  8. return actions

第五章:Admin管理后台 - 2:自定义Admin actions的更多相关文章

  1. 第五章:Admin管理后台 - 3:Admin文档生成器

    Django的admindocs应用可以从模型.视图.模板标签等地方获得文档内容. 一.概览 要激活admindocs,请按下面的步骤操作: 在INSTALLED_APPS内添加django.cont ...

  2. 第五章:Admin管理后台

    Django奉行Python的内置电池哲学.它自带了一系列在Web开发中用于解决常见问题或需求的额外的.可选工具.这些工具和插件,例如django.contrib.redirects都必须在setti ...

  3. django学习-23.admin管理后台的数据表数据的自定义展示

    目录结构 1.前言 2.自定义设置一张指定的数据表的列表展示内容 2.1.第一步:如果我们想让数据表[hello_person]里面的表字段值全部展示出来,需在应用[hello]里的[admin.py ...

  4. Admin管理后台

    Django奉行Python的内置电池哲学.它自带了一系列在Web开发中用于解决常见问题或需求的额外的.可选工具.这些工具和插件,例如django.contrib.redirects都必须在setti ...

  5. django学习-27.admin管理后台里:对列表展示页面的数据展示进行相关优化

    目录结构 1.前言 2.完整的操作步骤 2.1.第一步:查看ModelAdmin类和BaseModelAdmin类的源码 2.2.第二步:查看表animal对应的列表展示页面默认的数据展示 2.3.第 ...

  6. django学习-26.admin管理后台里:修改登录页面标题,修改登录框标题,修改首页标题

    目录结构 1.前言 2.完整的操作步骤 2.1.第一步:查看[site.py]的源码 2.2.第二步:在应用[hello]所在目录里的[admin.py]里重写三个属性的属性值 2.3.第三步:重启服 ...

  7. django学习-19.admin管理后台的配置和登录

    目录结构 1.前言 2.admin管理后台的配置和登录的完整操作流程 2.1.第一步: 在[settings.py]里对常量[INSTALLED_APPS]的值进行相关配置 2.2.第二步: 在[ur ...

  8. 16.-admin管理后台

    一.admin管理后台 Django提供给了比较完善的后台管理数据库接口,可供开发过程中调用和测试使用 Django会搜集所有已注册的模型类,为这些模型类提供数据管理界面,供开发者使用   命令:py ...

  9. Testlink1.9.17使用方法(第五章 测试用例管理)

    第五章 测试用例管理 QQ交流群:585499566 TestLink支持的测试用例的管理包含二层:分别为新建测试用例集(Test Suites).创建测试用例(Test Cases).可以把测试用例 ...

  10. “全栈2019”Java多线程第十五章:当后台线程遇到finally

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. spingboot打jar包

    pom.xml文件中packaging为jar <packaging>jar</packaging> 安装插件 <plugin> <groupId>or ...

  2. 查询postgresql表结构和索引

    通过系统数据字典查询表结构 selectcol.table_schema,col.table_name,col.ordinal_position,col.column_name,col.data_ty ...

  3. day05 Java网络编程socket 与多线程

    java网络编程 java.net.Socket Socket(套接字)封装了TCP协议的通讯细节,是的我们使用它可以与服务端建立网络链接,并通过 它获取两个流(一个输入一个输出),然后使用这两个流的 ...

  4. DNS原理与配置

    DNS介绍 域名管理系统DNS(Domain Name System)是域名解析服务器的意思,应用层协议,是互联网的一项服务. DNS作用是: 把域名转换成网络可以识别的ip地址,在通过IP地址访问主 ...

  5. 聊一聊 C# 后台GC 到底是怎么回事?

    一:背景 写这一篇的目的主要是因为.NET领域内几本关于阐述GC方面的书,都是纯理论,所以懂得人自然懂,不懂得人也没法亲自验证,这一篇我就用 windbg + 源码 让大家眼见为实. 二:为什么要引入 ...

  6. 流程控制语句break

    break语句 用于结束循环结构,通常与分支结构if一起使用 即非正常循环,在中间循环的时候直接退出 注意break打断的是循环语句,不是if语句 注意while循环中一般需要有改变变量这个操作,否则 ...

  7. rust中的ref

    理解Rust的引用与借用(好文链接) #![feature(core_intrinsics)] fn print_type_of<T>(_: T) { println!("{}& ...

  8. DBPack SQL Tracing 功能及数据加密功能详解

    上周,我们正式发布了 DBPack SQL Tracing 功能和数据加密功能,现对这两个功能做如下说明. SQL Tracing 通过 DBPack 代理开启的全局事务,会自动在 http head ...

  9. Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。

    前言: Taurus.MVC 微服务版本已经发布了:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单. 以前都是框架发布时写点相关功能点的文章,没有形成 ...

  10. 使用 Vagrant 在 VirtualBox 安装 Linux 虚拟机

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 1. 导入 2.工具介绍 3.通过Vagrant为VirtualBox安装CentOS 7 4.总结 文章推荐: 关 ...