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 编辑界面和操作的更多相关文章

  1. python工业互联网应用实战3—Django Admin列表

    Django Admin笔者使用下来可以说是Django框架的开发利器,业务model构建完成后,我们就能快速的构建一个增删查改的后台管理框架.对于大量的企业管理业务开发来说,可以快速的构建一个可发布 ...

  2. python工业互联网应用实战2—从需求开始

    前言:随着国家工业2025战略的推进,工业互联网发展将会提速,将迎来一个新的发展时期,越来越多的企业开始逐步的把产线自动化,去年年底投产的小米亦庄的智能工厂就是一个热议的新闻.小米/华为智能工厂只能说 ...

  3. python工业互联网应用实战3—模型层构建

    本章开始我们正式进入到实战项目开发过程,如何从需求分析获得的实体数据转到模型设计中来,变成Django项目中得模型层.当然,第一步还是在VS2019 IDE环境重创建一个工程项目,本文我们把工程名称命 ...

  4. python工业互联网应用实战7—业务层

    本章我们演示代码是如何"进化"的,实战的企业日常开发过程中,系统功能总伴随着业务的不断增加,早期简单的代码慢慢的越来越复杂,敏捷编程中的"禅"--简单设计.快速 ...

  5. python工业互联网应用实战6—任务分解

    根据需求定义"任务"是一个完整的业务搬运流程,整个流程涉及到多个机构(设备)分别动作执行多个步骤,所以依据前面的模型设计,需要把任务分解到多个连续的子任务(作业),未来通过顺序串联 ...

  6. python工业互联网应用实战8—django-simpleui

    笔者也使用过一段时间adminx组件,后来由于adminx停更,又遇到更简单的django-simpleui后,现在基本上只使用simpleui了,使用simpleui的几个好处,笔者认为排在第一位的 ...

  7. python工业互联网应用实战18—前后端分离模式之jquery vs vue

    前面我们分三章来说明了使用django template与jquery的差别,通过jquery如何来实现前后端的分离,同时再9章节使用vue.js 我们浅尝辄止的介绍了JQuery到vue的切换,由于 ...

  8. python工业互联网应用实战17—前后端分离模式之django template vs jquery3

    上一章节我们完成了"CRUD"的后面3个功能点,新增由于改动较大我们专门增加本章来阐述,主要是完成技术栈切换后,会发现模板的代码判断过多,逻辑过于复杂.对未来存在的扩展和维护友好性 ...

  9. python工业互联网应用实战1—SQL与ORM

    从sql到ORM应该说也是编程体系逐步演化的结果,通过类和对象更好的组织开个过程中遇到的各种业务问题,面向对象的解耦和内聚作为一套有效的方法论,对于复杂的企业应用而言确实能够解决实践过程中很多问题. ...

随机推荐

  1. python函数----名称空间和作用域

    一 名称空间 名称空间即存放名字与对象映射/绑定关系的地方. 对于x=3,Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中,del x表示清除该绑定关系. ​在程序执行 ...

  2. 风炫安全web安全学习第二十九节课 CSRF防御措施

    风炫安全web安全学习第二十九节课 CSRF防御措施 CSRF防御措施 增加token验证 对关键操作增加token验证,token值必须随机,每次都不一样 关于安全的会话管理(SESSION) 不要 ...

  3. 用python做youtube自动化下载器 思路

    目录 0. 思路 1.准备 i.savfrom.net 2. 探索并规划获取方式 i.总览 ii. 获取该网页取到下载url的请求 iii. 在本地获取请求 iv.解析请求结果 v.解析解密后的结果 ...

  4. Jenkins+GitLab+SonnarQube搭建CI/CD全流程

    1. CI/CD 1.1 CI - 持续集成 持续集成( Continuous integration , 简称 CI )指的是,频繁地(一天多次)将代码集成到主干.持续集成的目的就是让产品可以快速迭 ...

  5. JDK1.7-HashMap原理

    JDK1.7 HashMap 如何在源码上添加自己的注释 打开jdk下载位置 解压src文件夹,打开idea,ctrl+shift+alt+s打开项目配置 选择jdk版本1.7,然后点击Sourcep ...

  6. js 数组的方法总结

    1.Array.map() 此方法是将数组中的每个元素调用一个提供的函数,结果作为一个新的数组返回,并没有改变原来的数组 let arr = [1, 2, 3, 4, 5]     let newAr ...

  7. 基于Python的接口自动化-读写excel文件

    引言 使用python进行接口测试时常常需要接口用例测试数据.断言接口功能.验证接口响应状态等,如果大量的接口测试用例脚本都将接口测试用例数据写在脚本文件中,这样写出来整个接口测试用例脚本代码将看起来 ...

  8. 基于腾讯云存储网关 CSG 实现视频在线转码分发

    一.背景 随着越来越多的传统业务云化和云端业务发展,数据上云和云端数据处理领域的需求爆发式增长.腾讯云存储网关CSG提供一键部署开箱即用的便捷模式,深度结合COS对象存储生态,为用户提供方便快捷的数据 ...

  9. 【Nginx】yum安装nginx

    这里是nginx的yum安装源: centos7: rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-cent ...

  10. 基础Markdown语法

    Markdown语法 1.标题 //标题语法 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 一级标题 二级标题 三级标题 四级标题 ...