我们在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的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. GO基础知识分享

    目录 GO基础知识分享 go语言的基本事项 关键字 字符串的拼接和变量的定义方式 空白符 const常量 iota的用法 运算符 Go 没有三目运算符,不能适用?: 语言条件语句 for循环的方式 函 ...

  2. Docker遇到的异常和注意点

    Docker遇到的异常和注意点 整理一些使用docker的时候,遇到的问题和解决办法 遇到的一些异常和解决方法 删除镜像时出现: Error response from daemon: conflic ...

  3. 基于ceph rbd 在kubernetes harbor 空间下创建动态存储

    [root@bs-k8s-ceph ~]# ceph osd pool create harbor 128 Error ETIMEDOUT: crush test failed with -110: ...

  4. 宝塔linux7.4.2/windows6.8 的版本中的安全随笔

    在2020/8.23宝塔官方发布了一条关于宝塔linux7.4.2和Windows6.8版本中存在的重大的安全隐患 通知来源https://www.bt.cn/bbs/thread-54644-1-1 ...

  5. 磁盘lvm管理

    1.磁盘接口: 从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而SAS只在高端服务器 ...

  6. 手把手教你搭建自己的Angular组件库 - DevUI

    摘要:DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸.灵活.至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠.取悦眼球的设计.如果你正在开发 ToB 的工 ...

  7. 10276 - Hanoi Tower Troubles Again!(思维,模拟)

    People stopped moving discs from peg to peg after they know the number of steps needed to complete t ...

  8. SSDT表函数Hook原理

    其实 SSDT Hook 的原理是很简单的,我们可以知道在 SSDT 这个数组中呢,保存了系统服务的地址,比如对于 Ring0 下的 NtQuerySystemInformation 这个系统服务的地 ...

  9. [CTF]Rabbit加密

    [CTF]Rabbit加密 ---------------------  作者:adversity`  来源:CSDN  原文:https://blog.csdn.net/qq_40836553/ar ...

  10. Portswigger web security academy:OS command injection

    Portswigger web security academy:OS command injection 目录 Portswigger web security academy:OS command ...