python工业互联网应用实战15-前后端分离模式1
我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据加载和前端渲染主流开发方式,从而进一步实现前后端的解耦,提高Django开发Web应用的灵活性。
1.1. 修改任务列表模板
目前我们显示的任务列表是采用Django后台模板的方式加载数据的,要使用JQuery,同样采用探索编程方式,先实现前端加载模拟数据,Django模板只负责加载页面的基础架构,数据的渲染交由前端JQuery js脚本来实现加载模拟数据。
1.1.1. 修改tasks.html模板代码
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>任务列表</title>
</head>
<body>
<table id="id_task_table">
<tr>
<th>ID</th>
<th>任务号</th>
<th>源地址</th>
<th>目标地址</th>
<th>条码</th>
<th>状态</th>
<th>优先级</th>
<th>开始时间</th>
<th>结束时间</th>
<th>作业数量</th>
<th>操作</th>
</tr>
</table>
</body>
</html>
现在运行服务器,访问URL结果如下:

模板只只负责搭建要给页面的框架,数据通过JQuery来前端渲染。 页面的任务实例数据没有加载了,只显示了表格标题头。现在我们用JQuery脚本先给表格加载前端模式数据,先实现显示效果不变,逐步实现技术的切换。
1.1.2. JQuery动态添加任务列表行数据
JQuery脚本渲染代码如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>任务列表</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<table id="id_task_table">
<tr>
<th>ID</th>
<th>任务号</th>
<th>源地址</th>
<th>目标地址</th>
<th>条码</th>
<th>状态</th>
<th>优先级</th>
<th>开始时间</th>
<th>结束时间</th>
<th>作业数量</th>
<th>操作</th>
</tr>
</table>
<script>
var row="";
row +="<tr>";
row +="<td>1</td>";
row +="<td>100</td>";
row +="<td>103</td>";
row +="<td>05-01-01</td>";
row += "<td>101001001008</td>";
row += "<td>未处理</td>";
row += "<td>正常</td>";
row += "<td>-</td>";
row += "<td>-</td>";
row += "<td>2021-01-26 05:58:28</td>";
row += "<td>0</td>";
row += "<td><a id='1-decompose' href='1/decompose/'>分解</a> <a id='1-start' href='1/start/'>下达</a> <a id='1-change' href='1/change/'>修改</a></td>";
row +="</tr>";
$("#id_task_table tbody").append(row);
</script>
</body>
</html>
运行效果,我们发现页面渲染结果增加一行我们模拟添加的行任务数据。这样基于JQuery动态添加任务行的基本效果就实现了,下一步需要做的就是如何通过JQuery异步调用从后台获取数据后再通过上面的脚本实现任务数据在列表的渲染。
1.2. 改造任务后台
页面端ajax异步加载任务数据,需要后台能够返回json格式封装的任务数据。同理,采用渐进式方式先直接返回模拟多个任务的json格式任务数据url taskGetList。
1.2.1. taskGetList url
文件Task/urls 增加taskGetList url,对应Task/views文件增加taskGetList 函数,代码如下:
文件:Task/urls.py
from django.urls import path,re_path
from Task import views
urlpatterns = [
path('', views.view_list,name='view_list'),
re_path('^(?P<pk>\d+)/start/$',views.start,name='start'),#①
re_path('^(?P<pk>\d+)/change/$',views.change,name='change'),#②
re_path('^(?P<pk>\d+)/decompose/$',views.decompose,name='decompose'),
path('taskGetList/', views.taskGetList,name='taskGetList'),
]
文件:Task/views.py
from django.http import JsonResponse ... def taskGetList(request):
tasks=[]
task= {'TaskId':1,'TaskNum':100,'Source':'103','Target':'05-01-01','Barcode':'101001001008','State':1,'Priority':1,\
'BeginDate':None,'EndDate':None,'SystemDate':'2021-01-26 05:58',}
tasks.append(task)
tasks.append({'TaskId':2,'TaskNum':101,'Source':'102','Target':'05-01-11','Barcode':'101001001009','State':1,'Priority':1,\
'BeginDate':None,'EndDate':None,'SystemDate':'2021-01-26 06:00',}) data={"rows":tasks,'total':len(tasks),'success':True} #① return JsonResponse( data); #②
标注①:返回数据json格式封装,rows具体的任务List,total 返回总长度,sucess 是否成功。标注②:采用JsonResponse响应方式返回。
运行结果如下:http://localhost:8080/task/taskGetList/

1.3. 再次重构页面代码
Django开发后端url服务是不是也相当的简单,好的,接下来我们就可以前台通过ajax访问这个url服务获取数据并渲染到页面了。参考1章的调用方式代码如下:
<script>
//每次页面加载,ajax请求获取任务列表数据
getData()
function getData() {
//异步从后台获得值
$.ajax({
url: "/task/taskGetList/", success: function (result) {
//d = JSON.parse(result);
d = result
for (const task of d.rows) {
var row="";
row +="<tr>";
row +="<td>"+task.TaskId+"</td>";
row +="<td>"+task.TaskNum+"</td>";
row +="<td>"+task.Source+"</td>";
row +="<td>"+task.Target+"</td>";
row += "<td>"+task.Barcode+"</td>";
row += "<td>"+task.State+"</td>";
row += "<td>"+task.Priority+"</td>";
row += "<td>"+task.BeginDate+"</td>";
row += "<td>"+task.EndDate+"</td>";
row += "<td>"+task.SystemDate+"</td>";
row += "<td>"+task.JobCount+"</td>";
row += "<td><a id='" + task.TaskId + "-decompose' href='"+task.TaskId +"/decompose/'>分解</a> <a id='"+task.TaskId +"-start' href='"+task.TaskId +"/start/'>下达</a> <a id='"+task.TaskId +"-change' href='"+task.TaskId +"/change/'>修改</a></td>";
row +="</tr>";
$("#id_task_table tbody").append(row);
}
}});
}
</script>
运行效果,页面渲染结果采用了接口返回的数据。

1.4. 返回model层数据
本章节到这一步就是通过model层返回数据库表里的数据了,也就是如何model list系列化为字典格式,这里我们先采用model_to_dict实现model数据字典化,然后通过JsonResponse返回json格式数据。
from django.forms.models import model_to_dict
... def taskGetList(request):
tasks = []
taskList=Task.objects.all()
for model in taskList:
modelJson = model_to_dict(model)
modelJson['SystemDate'] = model.SystemDate #①
modelJson['JobCount'] =model.job_set.count() #②
tasks.append(modelJson)
data={"rows":tasks,'total':len(tasks),'success':True}
return JsonResponse( data);
标注①:model_to_dict不会转换有默认值的属,人工直接转换。标注②:python django笔者用起来很爽很爽的一点啊,可以方便的动态属性。
现在run一下http://localhost:8080/task/taskGetList/ 结果变成了这样:

改进一下日期格式,采用格式化函数格式化日期。
from django.forms.models import model_to_dict
... def taskGetList(request):
tasks = []
taskList=Task.objects.all()
for model in taskList:
modelJson = model_to_dict(model)
modelJson['SystemDate'] = model.SystemDate.strftime('%Y-%m-%d %H:%M:%S') #①
modelJson['JobCount'] =model.job_set.count()
tasks.append(modelJson)
data={"rows":tasks,'total':len(tasks),'success':True}
return JsonResponse( data);
标注①:采用strftime('%Y-%m-%d %H:%M:%S')把日期显示为24小时格式的。
现场运行开发服务,访问刷新http://localhost:8080/task/ 我们得到了代码重构前得效果,任务列表返回了数据库表的数据,但是一些字段没显示对照的中文函数
新版本

旧版本

进一步完善的服务端代码:
from django.forms.models import model_to_dict
def taskGetList(request):
tasks = []
taskList=Task.objects.all()
for model in taskList:
modelJson = model_to_dict(model)
modelJson['SystemDate'] = model.SystemDate.strftime('%Y-%m-%d %H:%M:%S')
modelJson['JobCount'] =model.JobCount() #①
modelJson['Priority'] =model.get_Priority_display()#②
modelJson['State'] =model.get_State_display()
tasks.append(modelJson)
data={"rows":tasks,'total':len(tasks),'success':True}
return JsonResponse( data);
标注①:JobCount移入到Model层,构成model的一个属性函数。标注②:直接返回优先级值的对照信息。
class Task(models.Model):
... def JobCount(self):
return self.job_set.count() JobCount.short_description='作业数量'
客户端代码:
<script>
getData() function getData() {
//模拟异步从后台获得值
$.ajax({
url: "/task/taskGetList/", success: function (result) {
//d = JSON.parse(result);
d = result
for (const task of d.rows) {
var row="";
row +="<tr>";
row +="<td>"+task.TaskId+"</td>";
row +="<td>"+task.TaskNum+"</td>";
row +="<td>"+task.Source+"</td>";
row +="<td>"+task.Target+"</td>";
row += "<td>"+task.Barcode+"</td>";
row += "<td>"+task.State+"</td>";
row += "<td>"+task.Priority+"</td>";
row += "<td>"+(task.BeginDate?task.BeginDate:'-')+"</td>";
row += "<td>"+(task.EndDate?task.EndDate:'-')+"</td>";
row += "<td>"+task.SystemDate+"</td>";
row += "<td>"+task.JobCount+"</td>";
row += "<td><a id='" + task.TaskId + "-decompose' href='"+task.TaskId +"/decompose/'>分解</a> <a id='"+task.TaskId +"-start' href='"+task.TaskId +"/start/'>下达</a> <a id='"+task.TaskId +"-change' href='"+task.TaskId +"/change/'>修改</a></td>";
row +="</tr>";
$("#id_task_table tbody").append(row);
}
}});
}
</script>
1.5. 小结
通过本章节内容,我们阐述了如何实现服务端与客户端分离的写法,并仍然采用稳步的渐进式改造方案,采用小步快跑的方式完成本次迭代。最后,我们在功能不变的前提下,完成了技术栈的迁移,把基于模板页渲染的django变成了基于模板框架js异步渲染的主流编程模式,下一章节我们将演示如何如何把编辑页面也进阶到前端渲染。
python工业互联网应用实战15-前后端分离模式1的更多相关文章
- python工业互联网应用实战18—前后端分离模式之jquery vs vue
前面我们分三章来说明了使用django template与jquery的差别,通过jquery如何来实现前后端的分离,同时再9章节使用vue.js 我们浅尝辄止的介绍了JQuery到vue的切换,由于 ...
- python工业互联网应用实战17—前后端分离模式之django template vs jquery3
上一章节我们完成了"CRUD"的后面3个功能点,新增由于改动较大我们专门增加本章来阐述,主要是完成技术栈切换后,会发现模板的代码判断过多,逻辑过于复杂.对未来存在的扩展和维护友好性 ...
- Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期
一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...
- AngularJS中在前后端分离模式下实现权限控制 - 基于RBAC
一:RBAC 百科解释: 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用 ...
- Vue的学习总结之---Vue项目 前后端分离模式解决开发环境的跨域问题
原文:https://blog.csdn.net/localhost_1314/article/details/83623526 在前后端分离的web开发中,我们与后台联调时,会遇到跨域的问题. 比如 ...
- python工业互联网应用实战2—从需求开始
前言:随着国家工业2025战略的推进,工业互联网发展将会提速,将迎来一个新的发展时期,越来越多的企业开始逐步的把产线自动化,去年年底投产的小米亦庄的智能工厂就是一个热议的新闻.小米/华为智能工厂只能说 ...
- python工业互联网应用实战16-前后端分离模式之修改与删除
前一章节介绍了List页面的JQuery技术栈的迁移,这一章节我们花一些篇幅来说说修改/查看页面的技术栈迁移.相对于List的获取数据,修改页面涉及到数据Post提交到后台更新数据库.我们仍旧小步迭代 ...
- python工业互联网应用实战3—模型层构建
本章开始我们正式进入到实战项目开发过程,如何从需求分析获得的实体数据转到模型设计中来,变成Django项目中得模型层.当然,第一步还是在VS2019 IDE环境重创建一个工程项目,本文我们把工程名称命 ...
- python工业互联网应用实战1—SQL与ORM
从sql到ORM应该说也是编程体系逐步演化的结果,通过类和对象更好的组织开个过程中遇到的各种业务问题,面向对象的解耦和内聚作为一套有效的方法论,对于复杂的企业应用而言确实能够解决实践过程中很多问题. ...
随机推荐
- python常见的错误异常
1.AssertionError 该异常在assert()语句运行失败时输出 2.AttributeError 该异常在参考或设置属性失败时输出 eg:class Gs: pass g = Gs() ...
- IPFS挖矿的成本有哪些?
IPFS作为区块链新贵,近来风头一时无量.截止3月9日,Filecoin以257亿的流通市值超越门罗币,稳居区块链流通排行榜. 无论什么投资,其门槛一定在成本.今天就和大家细说投资市面上常见实体矿机的 ...
- Redis扩展数据类型详解
在Redis中有5种基本数据类型,分别是String, List, Hash, Set, Zset.除此之外,Redis中还有一些实用性很高的扩展数据类型,下面来介绍一下这些扩展数据类型以及它们的使用 ...
- 快速排序(QuickSort)Java版
快速排序 快速排序是对冒泡排序的一种改进. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排 ...
- 设计Web页面(2)
1.前面我们新建了一个空白的ASP.NET网页,那么接下来这章我们就讲一下设计Web页面 2.布局页面有两种方法,一种是通过Table表格来布局页面窗体,另一种是通过CSS+DIV来布局窗体,其中作为 ...
- 【C/C++】memset方法的误区
目录 一.前言 二.函数作用 三.效率对比 四.误区总结 1.按字节设置 2.设置的值只有最低字节有效 3.堆内存不可直接 sizeof 取首地址 4.传参数组不可直接 sizeof 取首地址 一.前 ...
- KubeEdge EdgeMesh设计原理
EdgeMesh主要用来做边缘侧微服务的互访. ServiceMesh service mesh是一个服务网格的概念.在传统的架构里面都是通过像Dubbo来进行服务治理,服务治理的程序和我们应用程序强 ...
- 安装mmdetection,运行报错Segmentation fault
具体安装过程详见https://github.com/open-mmlab/mmdetection/blob/master/docs/INSTALL.md 在安装完成mmdetection后运行tes ...
- Java高级【Junit、反射、注解】
1.Junit单元测试 * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具体的执行流程. * Junit使用 ...
- Java(94-100)【数组、对象】
1.数组作为方法的参数 任何数据类型都可以作为方法的参数 直接建立数组的方法,将数组作为方法的参数. 当调用方法的时候传递的是数组的地址. 2.数组作为方法的返回值 任何数据类型都可以作为方法的参数, ...