python工业互联网应用实战5—Django Admin 编辑界面和操作
1.1. 编辑界面
默认任务的编辑界面,对于model属性包含“choices”会自动显示下来列表供选择,“datetime”数据类型也默认提供时间选择组件,如下图:

注意:“auto_now_add=True”的属性默认不会显示在编辑界面,外键字段会自动加载关联表数据,如上图操作员属性。
1.1.1. 设置要显示的模型属性
我们可以通过设置不显示操作员选项,代码如下:
fields=('TaskNum','Source','Target',Barcode','State','Priority','BeginDate','EndDate')
也可以采用exclude 属性设置排除不打算显示的模型属性。
exclude =('User',)
1.1.2. 设置一行显示多个属性
admin字段都是一个字段占一行,若想两个字段放在同一行显示,设置代码如下:
fields=('TaskNum',('Source','Target'),'Barcode','State','Priority','BeginDate','EndDate')
1.2. 编辑字段集合
model字段比较多的可以采用fieldsets,该设置可以对字段分块,让编辑界面看起来比较整洁和统一,代码如下:
fieldsets = (
("任务", {'fields': ['TaskNum', ('Source', 'Target'), 'Barcode','Priority',]}),
("摘要", {'fields':['State','BeginDate','EndDate']})
)
1.3. 设置只读字段
我们使用admin编辑界面的时候,会有些字段是不希望用户直接编辑的,那么通过重写get_readonly_fields()函数来实现这一功能,代码如下:
def get_readonly_fields(self, request, obj=None):
""" 重写此函数,设置只读字段 """
readonly_fields = ('State','BeginDate','EndDate')
return readonly_fields
1.4. 数据保存时自动登记操作员
我们希望操作员是由系统自动登记的,不能人为修改,通过重写ModelAdmin的save_model方法来实现。
def save_model(self, request, obj, form, change):
obj.User=request.user
return super().save_model(request, obj, form, change)
1.5. 任务下达操作
现在我们增加一个“下达”操作来变更任务的状态,把“处理成功”状态的任务变成修改成“执行中”状态。
# 增加自定义按钮
actions = ['task_start_action',] def task_start_action(self, request, queryset):
for obj in queryset:
if obj.State==4:
obj.State=5
try:
obj.save()
self.message_user(request, str(queryset[0].TaskNum) + " 下达成功.")
except Exception:
self.message_user(request, str(queryset[0].TaskNum) + " 下达失败.") else:
self.message_user(request, str(queryset[0].TaskNum) + " 下达失败.") task_start_action.short_description = '下达所选的' + ' 任务'

到这里,我们通过自定义按钮实现了对model的操作,把任务的状态从“处理完成”变更成“执行中”,本文我们将遵照“敏捷编程”中从简的业务宗旨来推进我们的功能实现。并演示代码如何通过重构来保证业务的不断迭代变更。
任务下达到“执行中”或“执行完成”后任务数据应该不允许再进行修改,需要把编辑页面变成数据浏览/查看页面。
1.6. 执行中和完成的任务状态全部字段只读设置
这里我们重构一下前面的get_readonly_fields函数,同时,通过数据库工具把其中1条数据状态设置成5,测试一下效果。
def get_readonly_fields(self, request, obj=None):
readonly_fields = ('State','BeginDate','EndDate','User')
if hasattr(obj, 'State'):
if obj.State in(5,99):
readonly_fields = ('TaskNum', 'Source', 'Target', 'Barcode','State','Priority','BeginDate','EndDate','User') return readonly_fields
1.7. 重构任务下达操作函数
1.6实现任务“下达”自定义按钮功能,操作起来需要先选择需要下达的行,然后再选择“下达所选的 任务”,最后点击执行操起起来过于繁琐,多行选择操作还好,单行选择操作就极度不符合用户的使用习惯。
通过重构任务下达函数,支持列表行操作“下达”功能,这样对于单行操作来说用户通过直接点击行的“操作”列下的“下达”链接即可以直接对数据行进行“下达”操作,提供人机界面的易用性。
1.7.1. 增加列操作功能
首先,我们增加列表操作功能列和行下达操作链接,代码和实现效果如下:
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... def task_operate(self,obj):
dest = 'taskStart/{}'.format(obj.pk)
title = '下达'
return format_html('<a href="{}">{}</a>'.format(dest, title)) task_operate.short_description = '操作'
1.7.2. 重构task_start_action函数,增加业务功能函数task_start()
我们task_start()函数把model的业务逻辑代码进行封装,通过这个函数的重用来保证,无论是通过action按钮还是功能列下达的业务逻辑是一致的。
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... # 增加自定义按钮
actions = ['task_start_action',] def task_start_action(self, request, queryset):
for obj in queryset:
result=self.task_start(obj)
if result:
self.message_user(request, str(obj.TaskNum) + " 下达成功.")
else:
self.message_user(request, str(obj.TaskNum) + " 下达失败.") task_start_action.short_description = '下达所选的' + ' 任务' def task_start(self,obj):
success=False
if obj.State==4:
obj.State=5
try:
obj.save()
success = True
except Exception:
success = False
return success
代码重构要点之一就是先确保满足原有业务功能的前提下,调整代码的结构,上面的代码增加的task_start并没有改变原先的业务逻辑,所以通过原来的action仍然能够正常下达选中的任务。
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... def task_operate(self,obj):
url = '{}/taskStart/'.format(obj.pk)
oprName = '下达'
return format_html('<a href="{}">{}</a>'.format(url, oprName)) task_operate.short_description = '操作'
接下来我们先增加操作列的下达链接操作,刷新列表页我们就能看到操作按钮链接了。然后,我们依据修改的url规则来构建taskStart url “/admin/Task/task/1/taskStart /”用来响应点击下达链接响应事件,代码如下:
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... def task_operate(self,obj):
url = '{}/taskStart/'.format(obj.pk)
oprName = '下达'
return format_html('<a href="{}">{}</a>'.format(url, oprName)) task_operate.short_description = '操作'
#task_operate.allow_tags = True def get_urls(self):
"""添加一个url,指向任务下达功能的函数taskStart()"""
from django.conf.urls import url
urls = [
re_path('(?P<pk>\d+)/taskStart/',
self.admin_site.admin_view(self.task_start_view),
name='task_start_view'),
]
return urls + super(TaskAdmin, self).get_urls() def task_start_view(self, request, *args, **kwargs): obj = get_object_or_404(Task, pk=kwargs['pk'])
self.task_start(obj) #数据更新成功后,重新刷新列表界面
co_path = request.path.split('/')
new_path=co_path[0:4]
new_path='/'.join(new_path)
return redirect(new_path)
现在我们在列表上点击“下达”链接,测试下达操作效果,效果如下图:

1.8. 模拟异常初窥事务
本章节我们演示了通过“下达”事件修改对应model的状态值,从而实现“任务”业务从一个状态到另一个状态的转换,现在我们通过一个模拟异常来演示也是事务的完整性问题,在一个业务操作里相关的业务数据变化要保持一致性。当出现异常需要回滚时,必须回滚所有涉及的对象(表)数据。
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... def task_start_view(self, request, *args, **kwargs): obj = get_object_or_404(Task, pk=kwargs['pk'])
self.task_start(obj)
raise Exception('模拟抛出异常!')
#重新刷新列表界面
co_path = request.path.split('/')
new_path=co_path[0:4]
new_path='/'.join(new_path)
request.path = new_path
return redirect(new_path)
上面的代码我们模拟调用self.task_start(obj)后,模拟出现异常,出现异常后应该需要回滚obj的状态,从而确保事务的一致性,尤其操作涉及到多个对象时,避免出现事务不一致的情况。由于现在代码没有事务约束机制,所以异常抛出后我们会发现obj的状态还是变更成“执行中”了。


现在增加事务约束来保证事务的一致性,再测试一遍发现变更的状态回滚回去了。
#Task模型的管理器
class TaskAdmin(admin.ModelAdmin):
... from django.db.transaction import atomic
@atomic
def task_start_view(self, request, *args, **kwargs): obj = get_object_or_404(Task, pk=kwargs['pk'])
self.task_start(obj)
raise Exception('模拟抛出异常!')
#重新刷新列表界面
co_path = request.path.split('/')
new_path=co_path[0:4]
new_path='/'.join(new_path)
request.path = new_path
return redirect(new_path)
1.9. 小结
本章节我们主要介绍了admin后台管理的编辑界面设置,通过两个章节完成了admin的初步介绍和设置,后面我们会根据内容的穿插admin的其它一些配置项。本章我们还简要的模拟演示了业务事务的一致性问题,当某一个业务操作过程中出现异常时,需要回滚当前的所有操作,事务的部分完成在企业的开发中是不能被允许的!
通过django admin我们快速的构建了一个任务的管理系统原型,下一章节我们将进一步增加功能讲述如何分解任务到作业(子任务),并通过代码重构改进代码的组织结构。
python工业互联网应用实战5—Django Admin 编辑界面和操作的更多相关文章
- python工业互联网应用实战3—Django Admin列表
Django Admin笔者使用下来可以说是Django框架的开发利器,业务model构建完成后,我们就能快速的构建一个增删查改的后台管理框架.对于大量的企业管理业务开发来说,可以快速的构建一个可发布 ...
- python工业互联网应用实战2—从需求开始
前言:随着国家工业2025战略的推进,工业互联网发展将会提速,将迎来一个新的发展时期,越来越多的企业开始逐步的把产线自动化,去年年底投产的小米亦庄的智能工厂就是一个热议的新闻.小米/华为智能工厂只能说 ...
- python工业互联网应用实战3—模型层构建
本章开始我们正式进入到实战项目开发过程,如何从需求分析获得的实体数据转到模型设计中来,变成Django项目中得模型层.当然,第一步还是在VS2019 IDE环境重创建一个工程项目,本文我们把工程名称命 ...
- python工业互联网应用实战7—业务层
本章我们演示代码是如何"进化"的,实战的企业日常开发过程中,系统功能总伴随着业务的不断增加,早期简单的代码慢慢的越来越复杂,敏捷编程中的"禅"--简单设计.快速 ...
- python工业互联网应用实战6—任务分解
根据需求定义"任务"是一个完整的业务搬运流程,整个流程涉及到多个机构(设备)分别动作执行多个步骤,所以依据前面的模型设计,需要把任务分解到多个连续的子任务(作业),未来通过顺序串联 ...
- python工业互联网应用实战8—django-simpleui
笔者也使用过一段时间adminx组件,后来由于adminx停更,又遇到更简单的django-simpleui后,现在基本上只使用simpleui了,使用simpleui的几个好处,笔者认为排在第一位的 ...
- python工业互联网应用实战18—前后端分离模式之jquery vs vue
前面我们分三章来说明了使用django template与jquery的差别,通过jquery如何来实现前后端的分离,同时再9章节使用vue.js 我们浅尝辄止的介绍了JQuery到vue的切换,由于 ...
- python工业互联网应用实战17—前后端分离模式之django template vs jquery3
上一章节我们完成了"CRUD"的后面3个功能点,新增由于改动较大我们专门增加本章来阐述,主要是完成技术栈切换后,会发现模板的代码判断过多,逻辑过于复杂.对未来存在的扩展和维护友好性 ...
- python工业互联网应用实战1—SQL与ORM
从sql到ORM应该说也是编程体系逐步演化的结果,通过类和对象更好的组织开个过程中遇到的各种业务问题,面向对象的解耦和内聚作为一套有效的方法论,对于复杂的企业应用而言确实能够解决实践过程中很多问题. ...
随机推荐
- Head First 设计模式 —— 08. 外观 (Facade) 模式
思考题 想想看,你在 JavaAPI 中遇到过哪些外观,你还希望 Java 能够新增哪些外观? P262 println.log 日志接口.JDBC 接口 突然让想感觉想不出来,各种 API 都用得挺 ...
- PHP 导入Excel数据 到数据库
/** * 导入excel * @throws \PHPExcel_Exception * @throws \PHPExcel_Reader_Exception */ public function ...
- 【Redis3.0.x】事务
Redis3.0.x 事务 基本概念 multi,exec,discard,watch 是 Redis 事务的基础,它们允许一步执行一组命令,有两个重要保证: 事务中的所有命令都被序列化并顺序执行.在 ...
- 【C++】《Effective C++》第二章
第二章 构造/析构/赋值运算 条款05:了解C++默默编写并调用哪些函数 默认函数 一般情况下,编译器会为类默认合成以下函数:default构造函数.copy构造函数.non-virtual析构函数. ...
- 搞定面试官:咱们从头到尾再说一次 Java 垃圾回收
接着前几天的两篇文章,继续解析JVM面试问题,送给年后想要跳槽的小伙伴 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题..... 万万没想到,JVM内存区域的面试题也可以问 ...
- ubuntu环境下搭建Hadoop集群中必须需要注意的问题
博主安装的hadoop是3.1.3这里是按照厦门大学那个博客安装的,在安装与启动过程中,费了不少事,特此记录一下问题. 安装的连接: 安装环境:http://dblab.xmu.edu.cn/blog ...
- Redis中哈希分布不均匀该怎么办
前言 Redis 是一个键值对数据库,其键是通过哈希进行存储的.整个 Redis 可以认为是一个外层哈希,之所以称为外层哈希,是因为 Redis 内部也提供了一种哈希类型,这个可以称之为内部哈希.当我 ...
- MongoDB分片集群部署方案
前言 副本集部署是对数据的冗余和增加读请求的处理能力,却不能提高写请求的处理能力:关键问题是随着数据增加,单机硬件配置会成为性能的瓶颈.而分片集群可以很好的解决这一问题,通过水平扩展来提升性能.分片部 ...
- 1.8V转5V电平转换芯片,1.8V转5V的电源芯片
1.8V是一个比较低的电压,在电压供电电压中,1.8V电压的过于小了,在一些电子模块或者MCU中,无法达到供电电压,和稳压作用,PW5100就是可以在1.8V转5V的电平转换电路和芯片,最大可提供50 ...
- 如何在K8s,Docker-Compose注入镜像Tag
最近在做基于容器的CI/CD, 一个朴素的自动部署的思路是: 从Git Repo打出git tag,作为镜像Tag ssh远程登录到部署机器 向部署环境注入镜像Tag,拉取镜像,重新部署 下面分享我是 ...




