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

1.1. 数据新增

  作为企业开发信息管理的核心“增/删/改/查”,目前为止我们涉及到了查询、修改和删除,现在我们来讲讲如何通过新增添加数据到系统吧。新增操作与修改删除不一样的就是新增的时候对象未在后台持久化到数据库中获取自身的对象标识,也就是说对象标识是空的或“0”,我们也是依据这点来判断数据是新增还是修改。如下图:参考admin新增必填项,其它为默认项。

1.1.1. 修改taskChange.html模板代码

  修改现在的taskChange.html模板,支持新增数据录入,本次模板改动较大主要是引入了bootstrap样式,代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title></title>
  6. <link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
  7. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  8. </head>
  9. <body>
  10. <div class="container">
  11. <h1>任务详情</h1>
  12. <div class="row"><div><b>对象标识:</b></div><div id="task_id">{{pk}}</div></div>
  13. {% if pk != '0' %} <!--①-->
  14. <div class="row"><div><b>任务号:</b></div><div id="task_num"></div></div>
  15. <form method="post" id="edit_form" hidden>
  16. <div class="row">
  17. <div><b>源地址:</b></div><input name="source" id="id_source" value="" />
  18. <div><b>目标地址:</b></div><input name="target" id="id_target" value="" />
  19. <input type="button" value="提交" onclick="saveData()">
  20. <input type="button" value="删除" onclick="delData()"> </div>
  21. </form>
  22. {% else %}
  23. <form method="post" id="edit_form">
  24. <div class="row"><div><b>任务号:</b></div><input name="task_num" id="id_task_num" value="" /></div>
  25. <div class="row"><div><b>源地址:</b></div><input name="source" id="id_source" value="" /></div>
  26. <div class="row"><div><b>目标地址:</b></div><input name="target" id="id_target" value="" /></div>
  27. <div class="row"><div><b>条码:</b></div><input name="barcode" id="id_barcode" value="" /><input type="button" value="提交" onclick="saveData()"></div>
  28. <div class="row"></div>
  29. </form>
  30. {% endif %}
  31. {% csrf_token %}
  32. <div class="row" id="div_source" hidden><div><b>源地址:</b></div><div id="source"></div></div>
  33. <div class="row" id="div_target" hidden><div><b>目标地址:</b></div><div id="target"></div></div>
  34. <div class="row" id="div_barcode" hidden><div><b>条码:</b></div><div id="barcode"></div></div>
  35.  
  36. <div class="row"><div><b>任务状态:</b></div><div id="state"></div></div>
  37. <div class="row"><div><b>优先级:</b></div><div id="priority"></div></div>
  38. <div class="row"><div><b>开始时间:</b></div><div id="begin_date"></div></div>
  39. <div class="row"><div><b>结束时间:</b></div><div id="end_date"></div></div>
  40. <div class="row"><div><b>作业数量:</b></div><div id="job_count"></div></div>
  41. </div>
  42. <script>
  43. if ($('#task_id').text() > 0) {
  44. $('#div_barcode').removeAttr('hidden')
  45. getData()
  46. }
  47. else
  48. $('#div_barcode').attr('hidden')
  49. function getData() {
  50. //异步从后台获得值
  51. url_str = "/task/taskGet/" + $('#task_id').text() + '/'
  52. $.ajax({
  53. url: url_str, success: function (result) {
  54. task = result.model
  55. if (task.State == '未处理') {
  56. $('#div_source').attr('hidden')
  57. $('#div_target').attr('hidden')
  58. $('#edit_form').removeAttr('hidden')
  59. $('#id_source').val(task.Source)
  60. $('#id_target').val(task.Target)
  61. } else {
  62. $('#edit_form').attr('hidden')
  63. $('#div_source').removeAttr('hidden')
  64. $('#div_target').removeAttr('hidden')
  65. $('#source').text(task.Source)
  66. $('#target').text(task.Target)
  67. }
  68. $('#task_num').text(task.TaskNum)
  69. $('#barcode').text(task.Barcode)
  70. $('#state').text(task.State)
  71. $('#priority').text(task.Priority)
  72. $('#begin_date').text(task.BeginDate)
  73. $('#end_date').text(task.EndDate)
  74. $('#job_count').text(task.JobCount)
  75. }
  76. })
  77. }
  78.  
  79. function saveData() {
  80. //异步提交数据到后台
  81. url_str = "/task/taskSave/" + $('#task_id').text() + '/'
  82. data = {
  83. source: $('#id_source').val(),
  84. target: $('#id_target').val(),
  85. csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
  86. }
  87. if ($('#task_id').text() <= 0) //②
  88. data.taskNum = $('#id_task_num').val()
  89. data.barcode = $('#id_barcode').val()
  90. $.ajax({
  91. type: 'POST', url: url_str, data: data, success: function (result) {
  92. window.location.replace("/task/");
  93. }
  94. });
  95. }
  96. function delData() {
  97. url_str = "/task/taskDel/"
  98. data = {
  99. pk: $('#task_id').text(),
  100. csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
  101. }
  102. $.ajax({
  103. type: 'POST', url: url_str, data: data, success: function (result) {
  104. window.location.replace("/task/");
  105. }
  106. });
  107. }
  108. </script>
  109. </body>
  110. </html>

  标注①:增加了对象标识来判断是修加载还是新增,页面html改动不是非常大,主要是增加css规范显示。标注②:如果新增提交参数增加任务编号和条码信息。

1.1.2. 修改后台taskSave代码支持新增model

  1. ...
  2. def taskSave(request,pk):
  3. if int(pk) > 0: #①
  4. data={"Source":request.POST['source'],"Target":request.POST['target']}
  5. model = Task.objects.filter(pk=pk).update(**data)
  6. else:
  7. data={"Source":request.POST['source'],"Target":request.POST['target'],"Barcode":request.POST['barcode'],\
  8. "TaskNum":request.POST['taskNum'], "State":1,"Priority":1,}
  9. model=Task.objects.create(**data)
  10.  
  11. data={'total':1,'success':True}
  12.  
  13. return JsonResponse(data)

  标注①:通过pk值判断新增还是修改操作。

1.1.3. 新增链接

  最后我们在tasks.html模板里增加一个新增链接,可以进入到新增窗口。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>任务列表</title>
  6. <link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
  7. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  8. </head>
  9. <body>
  10. <div><a href='0/change/'>新增</a></div>
  11. ...

1.1.4. 运行效果

1.2. 重构模板代码/查看

  现在的taskChange.html模板代码为了支持查看、修改和新增做了很多隐藏的区域,根据不同的model状态隐藏或显示不同的区域,这个的代码当页面功能复杂的时候,后期维护就会变成一个泥泞的沼泽,会让每个打算过草地的深陷泥潭。重构代码就是复杂的晦涩的代码修改成易读和简洁的代码,尽量让函数、类和模板等功能单一。

1.2.1. 查看模板taskView.html模板代码

  查看任务明细信息与修改分开两个模板来处理,把功能内聚到不同的文件里进行处理

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title></title>
  6. <link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
  7. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  8. </head>
  9. <body>
  10. <div class="container">
  11. <h1>任务详情</h1>
  12. <div class="row"><div><b>对象标识:</b></div><div id="task_id">{{pk}}</div></div>
  13. <div class="row" id="div_source" ><div><b>源地址:</b></div><div id="source"></div></div>
  14. <div class="row" id="div_target" ><div><b>目标地址:</b></div><div id="target"></div></div>
  15. <div class="row" id="div_barcode" ><div><b>条码:</b></div><div id="barcode"></div></div>
  16. <div class="row"><div><b>任务状态:</b></div><div id="state"></div></div>
  17. <div class="row"><div><b>优先级:</b></div><div id="priority"></div></div>
  18. <div class="row"><div><b>开始时间:</b></div><div id="begin_date"></div></div>
  19. <div class="row"><div><b>结束时间:</b></div><div id="end_date"></div></div>
  20. <div class="row"><div><b>作业数量:</b></div><div id="job_count"></div></div>
  21. </div>
  22. <script>
  23. if ($('#task_id').text() > 0) {
  24. getData()
  25. }
  26. function getData() {
  27. //异步从后台获得值
  28. url_str = "/task/taskGet/" + $('#task_id').text() + '/'
  29. $.ajax({
  30. url: url_str, success: function (result) {
  31. task = result.model
  32.  
  33. $('#task_num').text(task.TaskNum)
  34. $('#source').text(task.Source)
  35. $('#target').text(task.Target)
  36.  
  37. $('#barcode').text(task.Barcode)
  38. $('#state').text(task.State)
  39. $('#priority').text(task.Priority)
  40. $('#begin_date').text(task.BeginDate)
  41. $('#end_date').text(task.EndDate)
  42. $('#job_count').text(task.JobCount)
  43. }
  44. })
  45. }
  46. </script>
  47. </body>
  48. </html> 

  模板只专注于查看任务明细的功能,其它新增、修改录入的相关功能全部移除掉。

1.2.2. 发布taskView url

  文件:Task/urls.py

  1. from django.urls import path,re_path
  2. from Task import views
  3. urlpatterns = [
  4. ...
  5. re_path('^(?P<pk>\d+)/view/$',views.taskView,name='taskView'),#②
  6.  
  7. ] 

  文件:Task/views.py

  1. def taskView(request,pk):
  2. return render(request,'Task/taskView.html',{"pk":pk}) 

1.2.3. 修改tasks.html模板代码,增加查看链接

  1. function getData() {
  2. //模拟异步从后台获得值
  3. $.ajax({
  4. url: "/task/taskGetList/", success: function (result) {
  5. //d = JSON.parse(result);
  6. d = result
  7. for (const task of d.rows) {
  8. var row="";
  9. row +="<tr>";
  10. row +="<td>"+task.TaskId+"</td>";
  11. row +="<td><a href='"+task.TaskId +"/view/'>"+task.TaskNum +"</a></td>";//①
  12. row +="<td>"+task.Source+"</td>";
  13. row +="<td>"+task.Target+"</td>";
  14. row += "<td>"+task.Barcode+"</td>";
  15. row += "<td>"+task.State+"</td>";
  16. row += "<td>"+task.Priority+"</td>";
  17. row += "<td>"+(task.BeginDate?task.BeginDate:'-')+"</td>";
  18. row += "<td>"+(task.EndDate?task.EndDate:'-')+"</td>";
  19. row += "<td>"+task.SystemDate+"</td>";
  20. row += "<td>"+task.JobCount+"</td>";
  21. row += "<td><a id='" + task.TaskId + "-decompose' href='" + task.TaskId + "/decompose/'>分解</a> <a id='" + task.TaskId + "-start' href='" + task.TaskId + "/start/'>下达</a>"
  22. +(task.State=='未处理'?" <a id='" + task.TaskId + "-change' href='" + task.TaskId + "/change/'>修改</a>" :"" )
  23. + " <a id='" + task.TaskId + "-delete' href='#' onclick=taskDel(" + task.TaskId + ")>删除</a></td>";
  24. row +="</tr>";//②
  25.  
  26. $("#id_task_table tbody").append(row);
  27. }
  28. }
  29. });
  30. }

  标注①:增加查看链接;标注②:只能修改“未处理”状态的任务

  运行效果

1.3. 重构模板代码/修改

  重构代码把新增和修改内聚到taskChange.html模板下,代码聚焦在新增和修改下,不在考虑查看的相关功能处理。

1.3.1. 修改taskChange.html模板代码

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title></title>
  6. <link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
  7. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  8. </head>
  9. <body>
  10. <div class="container">
  11. <h1>任务详情</h1>
  12. <div class="row"><div><b>对象标识:</b></div><div id="task_id">{{pk}}</div></div>
  13. <form method="post" id="edit_form">
  14. <div class="row"><div><b>任务号:</b></div><input name="task_num" id="id_task_num" value="" /></div>
  15. <div class="row"><div><b>源地址:</b></div><input name="source" id="id_source" value="" /></div>
  16. <div class="row"><div><b>目标地址:</b></div><input name="target" id="id_target" value="" /></div>
  17. <div class="row"><div><b>条码:</b></div><input name="barcode" id="id_barcode" value="" /><input type="button" value="提交" onclick="saveData()"></div>
  18. <div class="row"></div>
  19. {% csrf_token %}
  20. </form>
  21. <div class="row"><div><b>任务状态:</b></div><div id="state"></div></div>
  22. <div class="row"><div><b>优先级:</b></div><div id="priority"></div></div>
  23. <div class="row"><div><b>开始时间:</b></div><div id="begin_date"></div></div>
  24. <div class="row"><div><b>结束时间:</b></div><div id="end_date"></div></div>
  25. <div class="row"><div><b>作业数量:</b></div><div id="job_count"></div></div>
  26. </div>
  27. <script>
  28. if ($('#task_id').text() > 0) {
  29. getData()
  30. }
  31. function getData() {
  32. //异步从后台获得值
  33. url_str = "/task/taskGet/" + $('#task_id').text() + '/'
  34. $.ajax({
  35. url: url_str, success: function (result) {
  36. task = result.model
  37. if (task.State == '未处理') { //②
  38. $('#id_task_num').attr('disabled',true)
  39. $('#id_barcode').attr('disabled',true)
  40. } else {
  41. $('#id_task_num').removeAttr('disabled')
  42. $('#id_barcode').removeAttr('disabled')
  43. }
  44.  
  45. $('#id_source').val(task.Source)
  46. $('#id_target').val(task.Target)
  47. $('#id_task_num').val(task.TaskNum)
  48. $('#id_barcode').val(task.Barcode)
  49.  
  50. $('#state').text(task.State)
  51. $('#priority').text(task.Priority)
  52. $('#begin_date').text(task.BeginDate)
  53. $('#end_date').text(task.EndDate)
  54. $('#job_count').text(task.JobCount)
  55. }
  56. })
  57. }
  58. ...

  59. </script>
  60. </body>
  61. </html> 

  标注①:删除复杂的if渲染模板;标注②:修改状态把不允许修改的input属性设为只读状态

1.4. 小结

  代码重构完成后查看与新增/修改的url和view的处理就分开了成两个分支了,重构让每一部分的代码更专注与相关功能,从而减少条件判断,提高代码的可读性。尽量不要在一个函数里囊括过多的功能、尽量不要在一个类里包括过多的功能、尽量也不要在一个模板里包含太多的功能。让代码高内聚(功能聚焦)低耦合,是高质量代码、提高代码可读性和简洁性的不二法宝。当你的函数臃肿、当你的类功能臃肿、当你的模板代码臃肿,重构代码吧,让它简单读、简洁可读、简明易读!

python工业互联网应用实战17—前后端分离模式之django template vs jquery3的更多相关文章

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

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

  2. Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期

    一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...

  3. AngularJS中在前后端分离模式下实现权限控制 - 基于RBAC

    一:RBAC 百科解释: 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用 ...

  4. python工业互联网应用实战15-前后端分离模式1

    我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据 ...

  5. Vue的学习总结之---Vue项目 前后端分离模式解决开发环境的跨域问题

    原文:https://blog.csdn.net/localhost_1314/article/details/83623526 在前后端分离的web开发中,我们与后台联调时,会遇到跨域的问题. 比如 ...

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

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

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

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

  8. python工业互联网应用实战16-前后端分离模式之修改与删除

    前一章节介绍了List页面的JQuery技术栈的迁移,这一章节我们花一些篇幅来说说修改/查看页面的技术栈迁移.相对于List的获取数据,修改页面涉及到数据Post提交到后台更新数据库.我们仍旧小步迭代 ...

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

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

随机推荐

  1. Ananagrams UVA - 156

      Most crossword puzzle fans are used to anagrams - groups of words with the same letters in differe ...

  2. Box UVA - 1587

    Ivan works at a factory that produces heavy machinery. He has a simple job - he knocks up wooden box ...

  3. NumPy之:标量scalars

    目录 简介 scalar类型的层次结构 内置Scalar类型 boolean Integers Unsigned integers Floating-point numbers Complex flo ...

  4. JavaScript实现斐波那契数列

    什么是斐波那契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为&qu ...

  5. 爬虫简介、requests 基础用法、urlretrieve()

    1. 爬虫简介 2. requests 基础用法 3. urlretrieve() 1. 爬虫简介 爬虫的定义 网络爬虫(又被称为网页蜘蛛.网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程 ...

  6. python进阶(17)偏函数partial

    什么是偏函数partial python中提供一种对于函数固定属性的函数 偏函数的作用 把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数 偏函数的语法 使用偏函数必须先导入from ...

  7. python3使用迭代生成器yield减少内存占用

    技术背景 在python编码中for循环处理任务时,会将所有的待遍历参量加载到内存中.其实这本没有必要,因为这些参量很有可能是一次性使用的,甚至很多场景下这些参量是不需要同时存储在内存中的,这时候就会 ...

  8. 病毒木马查杀实战第024篇:MBR病毒之编程解析引导区

    前言 通过之前的学习,相信大家已经对磁盘的引导区有了充分的认识.但是我们之前的学习都是利用现成的工具来对引导区进行解析的,而对于一名反病毒工程师而言,不单单需要有扎实的逆向分析功底,同时也需要有很强的 ...

  9. Linux中常见的150个命令(干货)

    目录 线上查询及帮助命令 文件和目录操作命令 查看文件和内容处理命令 文件压缩及解压缩命令 信息显示命令 搜索文件命令 进程管理相关命令 用户管理命令 基础网络操作命令 深入网络操作命令 有关磁盘与文 ...

  10. Win64 驱动内核编程-15.回调监控注册表

    回调监控注册表 在 WIN32 平台上,监控注册表的手段通常是 SSDT HOOK.不过用 SSDT HOOK 的方式监控注册表实在是太麻烦了,要 HOOK 一大堆函数,还要处理一些 NT6 系统有而 ...