前一章节介绍了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-前后端分离模式之修改与删除的更多相关文章

  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. python工业互联网应用实战15-前后端分离模式1

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

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

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

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

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

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

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

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

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

随机推荐

  1. 由一名保安引发的Java设计模式:外观模式

    目录 应用场景 外观模式 定义 意图 主要解决问题 何时使用 优缺点 结构 保安的故事 应用场景 使用方要完成一个功能,需要调用提供方的多个接口.方法,调用过程复杂时,我们可以再提供一个高层接口(新的 ...

  2. Jmeter接口测试-MD5加密-请求验签(完整流程)

    第一部分:先准备好Jmeter 1.在开始编写脚本之前,先要确保你的Jmeter能够正常运行.若你还没有安装Jmeter,可参考以下方法: A.Jmeter需要java运行环境,所以需要下载JDK,J ...

  3. 死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  4. shopify 学习链接整理

    shopify shopify packagist https://help.shopify.com/zh-CN/manual/apps/apps-by-shopify/script-editor/s ...

  5. 关于Eclipse Debug断点调试出现 Search not found 页面的解决办法

    1. 在代码中鼠标右键 Debug AS ---> Debug Configurations... ----> 找到Source选项  ---> 点击add ---> 选择 j ...

  6. 【Idea】实用的快捷键清单

    1.Ctrl + Shift +i:快速查看某个类/方法 2.Ctrl +:(Ace Jump插件启动) 3.alt+F1:快速查看某个类/方法 所在的包 4.Ctrl +w :选中某个单词 5.Ct ...

  7. 从苏宁电器到卡巴斯基第27篇:难忘的三年硕士时光 V

    一发不可收拾 安全领域的公司都喜欢在看雪或者是吾爱破解这样的网站上发布招聘贴,因为这样的话很容易就能够招到适合的人才,也算是精准营销了.而像我这种想进入安全圈的,也会在这里发布自己的求职简历,以期望能 ...

  8. DLL内存加载

    动态加载dll 功能:      把一个处于内存里的dll直接加载并且使用. 用途:      免杀(静态文件查杀),外挂(防止游戏自己hook了loadlibrary等函数),以及其他. 原理:  ...

  9. 将大量ASCII码值转换成字符函数CHR()的小技巧

    一.在学习命令执行漏洞的过程中,遇到以下情况: 当服务器上传不了马或者马被过滤的时候,我们可以迂回一下,通过执行写马命令到服务器,在服务器里面写马,该命令是通过ascii编码过的命令,防止被过滤. 1 ...

  10. 3-5年以上的Android原生开发如何深入进阶?高级工程师必须要掌握哪些?

    前言 曾听过很多人说Android学习很简单,做个App就上手了,工作机会多,毕业后也比较容易找工作.这种观点可能是很多Android开发者最开始入行的原因之一. 在工作初期,工作主要是按照业务需求实 ...