python工业互联网应用实战16-前后端分离模式之修改与删除
前一章节介绍了List页面的JQuery技术栈的迁移,这一章节我们花一些篇幅来说说修改/查看页面的技术栈迁移。相对于List的获取数据,修改页面涉及到数据Post提交到后台更新数据库。我们仍旧小步迭代的方式推进,修改/查看页面的技术迁移。
1.1. 修改/查看页面分离
修改/查看页面分离与列表的前后台分离会相对复杂一些,主要时是修改页面会涉及到通过POST向后台提交数据修改。基于模板的方式加载数据,技术上是通过view的change函数里增加POST分支来实现数据提交的,提交成功后重定向加载列表url,我们先沿用这一思路采用前后台分离的模式来重构我们的修改/查看页面。
1.1.1. 修改模板taskChange.html
<!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>
<h1>任务详情</h1>
<div id="task_id"></div>
<div id="task_num"></div>
<form method="post" id="edit_form" hidden>
<input name="source" id="id_source" value="" />
<input name="target" id="id_target" value="" />
<input type="submit" value="提交">
{% csrf_token %}
</form>
<div id="source"></div>
<div id="target"></div>
<div id="state"></div>
<div id="priority"></div>
<div id="begin_date"></div>
<div id="end_date"></div>
<div id="job_count"></div>
<script>
task = {
"TaskId": 2,
"TaskNum": 102,
"Source": "101",
"Target": "05-01-02",
"Barcode": "101001001010",
"State": "处理成功",
"Priority": "紧急",
"BeginDate": null,
"EndDate": null,
"User": 1,
"SystemDate": "2021-01-26 05:59:45",
"JobCount": 10
}
getData()
function getData() {
#① 数据显示绑定的赋值代码
$('#task_id').text(task.TaskId)
$('#task_num').text(task.TaskNum)
$('#source').text(task.Source)
$('#target').text(task.Target)
$('#barcode').text(task.Barcode)
$('#state').text(task.State)
$('#priority').text(task.Priority)
$('#begin_date').text(task.BeginDate)
$('#end_date').text(task.EndDate)
$('#job_count').text(task.JobCount)
}
</script>
</body>
</html>
标注①:getData函数里,数据显示绑定的赋值代码。
运行效果
1.1.2. 改造任务获取后台
接下来,我们通过增加taskGet函数通过传入对象pk来获取对象的json数据。获取数据的url“ http://localhost:8080/task/taskGet/1/”,获取pk=1的model对象数据。
Task/urls.py文件
from django.urls import path,re_path
from Task import views
urlpatterns = [
...
path('taskGetList/', views.taskGetList,name='taskGetList')
re_path('taskGet/(?P<pk>\d+)/$',views.taskGet,name='taskGet'),#① ]
标注①:通过传入pk参数来获取单个model的json格式数据。
Task/urls.py文件
...
def taskGet(request,pk):
model = get_object_or_404(Task, pk=pk)#①
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() return JsonResponse({"model":modelJson,'total':1,'success':True})
标注①:通过传入pk参数来获取单个model的json格式数据。
运行结果: http://localhost:8080/task/taskGet/1/
1.1.3. 再次重构taskChange.html
<!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>
<h1>任务详情</h1>
<div id="task_id">{{pk}}</div> <!--①-->
<div id="task_num"></div>
<form method="post" id="edit_form" hidden>
<input name="source" id="id_source" value="" />
<input name="target" id="id_target" value="" />
<input type="submit" value="提交">
{% csrf_token %}
</form>
<div id="source"></div>
<div id="target"></div>
<div id="state"></div>
<div id="priority"></div>
<div id="begin_date"></div>
<div id="end_date"></div>
<div id="job_count"></div> <script>
getData() function getData() {
//异步从后台获得值
url_str = "/task/taskGet/"+ $('#task_id').text() //②
$.ajax({ url: url_str , success: function (result) {
task = result.model
$('#task_num').text(task.TaskNum)
$('#source').text(task.Source)
$('#target').text(task.Target)
$('#barcode').text(task.Barcode)
$('#state').text(task.State)
$('#priority').text(task.Priority)
$('#begin_date').text(task.BeginDate)
$('#end_date').text(task.EndDate)
$('#job_count').text(task.JobCount)
}
});
}
</script>
</body>
</html>
标注①:模板需要把请求的pk值,赋值到前端组件,这个很重要所有单个对象均是用pk来获取的。 标注②:前端通过页面组件的pk值,异步获取到任务的json格式数据,并加载显示。
这里我们同样需要改进一下views函数change函数把获取到的pk值,渲染到前端。
@atomic
def change(request,pk):
if request.method=='GET':
return render(request,'Task/taskChange.html',{"pk":pk})#①
elif request.method=='POST':
data={"Source":request.POST['source'],"Target":request.POST['target']}
Task.objects.filter(pk=pk).update(**data) return __reloadTasksPage(request)
标注①:需要把请求的pk值,传到前端模板,原来是直接传入对象到模板。
现在访问地址:http://localhost:8080/task/3/change/结果如下图:
1.2. 提交数据
进一步重构客户端代码,实现可以修改任务为“未处理”状态的源地址和目标地址数据,并提交数据到后台。
<script>
getData()
function getData() {
//异步从后台获得值
url_str = "/task/taskGet/"+ $('#task_id').text() //②
$.ajax({
url: url_str , success: function (result) {
task = result.model
if (task.State == '未处理') {
$('#source').attr('hidden')
$('#target').attr('hidden')
$('#edit_form').removeAttr('hidden')
$('#id_source').val(task.Source)
$('#id_target').val(task.Target) } else {
$('#edit_form').attr('hidden')
$('#source').removeAttr('hidden')
$('#target').removeAttr('hidden')
$('#source').text(task.Source)
$('#target').text(task.Target)
}
$('#task_num').text(task.TaskNum)
$('#barcode').text(task.Barcode)
$('#state').text(task.State)
$('#priority').text(task.Priority)
$('#begin_date').text(task.BeginDate)
$('#end_date').text(task.EndDate)
$('#job_count').text(task.JobCount)
}
});
}
</script>
运行结果
至此,我们完成了修改页面客户与服务端的代码分离,从而实现了django模板页的解耦。我们构建了基于django的框架下的客户端、服务端主流的开发模式。
1.3. 异步POST数据
目前为止我们提交数据仍然是采用模板方式提交的,如何采用ajax post到后台呢?本小节我们着手处理post的异步提交。
1.3.1. 增加taskSave url
参考前面的views 函数taskGet新增做一个taskSave 并发布url。
from django.urls import path,re_path
from Task import views
urlpatterns = [
...
re_path('taskGet/(?P<pk>\d+)/$',views.taskGet,name='taskGet'),
re_path('taskSave/(?P<pk>\d+)/$',views.taskSave,name='taskSave'),#① ]
文件:Task/views.py
...
def taskSave(request,pk):
data={"Source":request.POST['source'],"Target":request.POST['target']}
model = Task.objects.filter(pk=pk).update(**data)
data={'total':model,'success':True}
return JsonResponse(data)
1.3.2. 修改页面代码
...
<form method="post" id="edit_form" hidden> <input name="source" id="id_source" value="" />
<input name="target" id="id_target" value="" />
<input type="button" value="提交" onclick="saveData()" > <!--①-->
{% csrf_token %}
</form>
标注①:修改提交按钮采用JQuery自定义click事件处理数据提交。
<script>
...
function saveData() {
//异步从后台获得值
url_str = "/task/taskSave/"+ $('#task_id').text() + '/' //①
data = {
source: $('#id_source').val(),
target: $('#id_target').val(),
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val() //②
}
$.ajax({
type: 'POST',url: url_str, data: data, success: function (result) {
//alert('HEHE')
window.location.replace("/task/"); //③
}
}); }
</script>
标注①:数据POST url 例子:/task/taskSave/1/,意思是更新pk=1的model数据。标注②:一定要传回这个参数,否则会报csrf验证失败。标注③:成功修改后从定向url到“/task/”。
1.4. 数据删除
作为企业开发增/删/改/查,目前为止我们涉及到了查询和修改,另外两个重要的就是新增和删除,通过新增添加数据,通过删除操作删除不需要的数据。
1.4.1. 删除操作
我们先来说删除操作,与修改的关键是对象标识(pk),同理,删除也是通过对象标识来进行。我们在查看页面增加删除按钮,来完成删除操作。删除某个任务涉及到后台数据的变化,常规采用POST方式来完成数据提交,这里我们把url设计成:/task/taskDel与保存函数类似的范式,但是不在url中显示要删除的pk值,pk作为post参数传递。
文件:Task/urls.py
from django.urls import path,re_path
from Task import views
urlpatterns = [
...
path('taskGetList/', views.taskGetList,name='taskGetList'),
re_path('taskGet/(?P<pk>\d+)/$',views.taskGet,name='taskGet'),
re_path('taskSave/(?P<pk>\d+)/$',views.taskSave,name='taskSave'),
path('taskDel/',views.taskDel,name='taskDel'),#①
]
标注①:不在显示传入pk参数,通过post隐式方式传入对象标识。
文件:Task/views.py
...
def taskDel(request):
data={'total':0,'success':False}
if request.method=='POST':
pk=request.POST['pk']#①
model = Task.objects.filter(pk=pk).delete()
data={'total':model,'success':True} #②
return JsonResponse(data)
标注①:获取POST请求里的pk参数。标注②:后台接口返回成功与失败,前端来判断后续的处理。
文件:模板taskChange.html
<!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>
<h1>任务详情</h1>
<div id="task_id">{{pk}}</div>
<div id="task_num"></div>
<form method="post" id="edit_form" hidden> <input name="source" id="id_source" value="" />
<input name="target" id="id_target" value="" />
<input type="button" value="提交" onclick="saveData()" >
<input type="button" value="删除" onclick="delData()" > <!--①-->
{% csrf_token %}
</form>
<div id="source"></div>
<div id="target"></div>
<div id="state"></div>
<div id="priority"></div>
<div id="begin_date"></div>
<div id="end_date"></div>
<div id="job_count"></div>
<script>
getData()
function getData() {
//异步从后台获得值
url_str = "/task/taskGet/" + $('#task_id').text() + '/'
$.ajax({
url: url_str, success: function (result) {
task = result.model
if (task.State == '未处理') {
$('#source').attr('hidden')
$('#target').attr('hidden')
$('#edit_form').removeAttr('hidden')
$('#id_source').val(task.Source)
$('#id_target').val(task.Target)
} else {
$('#edit_form').attr('hidden')
$('#source').removeAttr('hidden')
$('#target').removeAttr('hidden')
$('#source').text(task.Source)
$('#target').text(task.Target)
}
$('#task_num').text(task.TaskNum)
$('#barcode').text(task.Barcode)
$('#state').text(task.State)
$('#priority').text(task.Priority)
$('#begin_date').text(task.BeginDate)
$('#end_date').text(task.EndDate)
$('#job_count').text(task.JobCount)
}
}) } function saveData() {
//异步从后台获得值
url_str = "/task/taskSave/"+ $('#task_id').text() + '/'
data = {
source: $('#id_source').val(),
target: $('#id_target').val(),
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
}
$.ajax({
type: 'POST',url: url_str, data: data, success: function (result) {
window.location.replace("/task/");
}
});
} function delData() {
//异步从后台获得值
url_str = "/task/taskDel/" //①
data = {
pk: $('#task_id').text(),
csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val()
}
$.ajax({
type: 'POST',url: url_str, data: data, success: function (result) {
window.location.replace("/task/"); //②
}
});
}
</script>
</body>
</html>
标注①:注意没有传入pk参数。标注②:后台返回成功后,重定向页面到列表页面。
运行程序,在列表页面点击修改进入修改页面,未处理的任务我就可以点击删除按钮删除这条任务记录了,然后重新定向到列表页面就会发现重新刷新的类别没有那条任务记录了,删除操作成功!
1.5. 运行效果
1.6. 小结
通过本章节内容,我们完成了从列表到修改界面的服务端与客户端分离的写法,并仍然采用稳步的渐进式改造方案,采用小步快跑的方式完成本次迭代。最后,我们在功能不变的前提下,完成了技术栈的迁移,把基于模板页渲染的django变成了基于模板框架js异步渲染的主流编程模式。通过例子完整的演示了django如何实现企业开发中遇到“增/删/查/修/”后面3个问题,新增相对较为复杂,我们留给下一章节来重点讲述。
python工业互联网应用实战16-前后端分离模式之修改与删除的更多相关文章
- 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中,权限与角色相关联,用 ...
- python工业互联网应用实战15-前后端分离模式1
我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据 ...
- Vue的学习总结之---Vue项目 前后端分离模式解决开发环境的跨域问题
原文:https://blog.csdn.net/localhost_1314/article/details/83623526 在前后端分离的web开发中,我们与后台联调时,会遇到跨域的问题. 比如 ...
- python工业互联网应用实战2—从需求开始
前言:随着国家工业2025战略的推进,工业互联网发展将会提速,将迎来一个新的发展时期,越来越多的企业开始逐步的把产线自动化,去年年底投产的小米亦庄的智能工厂就是一个热议的新闻.小米/华为智能工厂只能说 ...
- python工业互联网应用实战3—模型层构建
本章开始我们正式进入到实战项目开发过程,如何从需求分析获得的实体数据转到模型设计中来,变成Django项目中得模型层.当然,第一步还是在VS2019 IDE环境重创建一个工程项目,本文我们把工程名称命 ...
- python工业互联网应用实战1—SQL与ORM
从sql到ORM应该说也是编程体系逐步演化的结果,通过类和对象更好的组织开个过程中遇到的各种业务问题,面向对象的解耦和内聚作为一套有效的方法论,对于复杂的企业应用而言确实能够解决实践过程中很多问题. ...
随机推荐
- 「性能提升」扩展 Spring Cache 支持多级缓存
为什么多级缓存 缓存的引入是现在大部分系统所必须考虑的 redis 作为常用中间件,虽然我们一般业务系统(毕竟业务量有限)不会遇到如下图 在随着 data-size 的增大和数据结构的复杂的造成性能下 ...
- 解决Spring中使用Example无法查询到Mongodb中的数据问题
1 问题描述 在Spring Boot中使用Mongodb中的Example查询数据时查询不到,示例代码如下: ExampleMatcher matcher = ExampleMatcher.matc ...
- element UI el-autocomplete 带输入建议的输入框
项目需求:需要用户在输入框中输入公司 全名 但是为了避免用户输入不全 需要做一个带输入建议的输入框 参考:https://www.jianshu.com/p/de922caf337c
- Spring-@PostConstruct注解
@PostConstruct注解 @PostConstruct注解好多人以为是Spring提供的.其实是Java自己的注解. Java中该注解的说明:@PostConstruct该注解被用来修饰一个非 ...
- w1R3s靶机work_through
前言 这靶机挺简单的.虽然网友们有分享oscp向的靶机集,但是没有一个难度梯度,做起来就怪怪的. 打点 nmap -sP 192.168.218.0/24 发现主机IP 192.168.218.134 ...
- 技术面试问题汇总第001篇:猎豹移动反病毒工程师part1
我在2014年7月1日参加了猎豹移动(原金山网络)反病毒工程师的电话面试,但是很遗憾,由于我当时准备不足,加上自身水平不够,面试官向我提出的很多技术问题我都没能答出来(这里面既有基础类的问题,也有比较 ...
- [转]自建CDN防御DDoS
自建CDN防御DDoS(1):知己知彼,建设持久防线 前言 本议题是我们在OWASP杭州区2013年岁末年初安全沙龙中进行分享的内容,在此我们对这个议题的整体内容进行了重新归纳梳理,形成了文字版. 在 ...
- ZOJ3715 竞选班长求最小花费
题意: 有n个小朋友竞选班长,一号想当班长,每个人都必须选择一个人当班长,并且不可以选择自己,并且每个人都有一个权值ai,这个权值就是如果1想让这个人改变主意选择自己当班长就得给他ai个糖 ...
- Python中zipfile压缩文件模块的使用
目录 zipfile 压缩一个文件 解压文件 高级应用 利用 zipfile 模块破解压缩文件口令:Python脚本破解压缩文件口令 zipfile Python 中 zipfile 模块提供了对 z ...
- CString,string,char数组的转换
来源:http://ticktick.blog.51cto.com/823160/317550 //----------------ANSI字符串转换为UNICODE字符串-------------- ...