前一章节介绍了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. ret2dl32

    ret2dl32 首先检查一下保护: IDA分析一下 程序很简单就是,往bss段上的buf读入0x400个数据,然后拷贝到栈上.read_got还被置为0,这一看就是要逼着你使用ret2dlresol ...

  2. 【Redis破障之路】三:Redis单线程架构

    众所周知,Redis是一个单线程架构的NoSQL数据库,但是是单线程模型的Redis为什么性能如此之高?这就是我们接下来要探究学习的内容. 1.Redis的单线程架构 1.1.Redis单线程简介 首 ...

  3. .NET RulesEngine(规则引擎)

    一次偶然的机会,让我拿出RulesEngine去完成一个业务,对于业务来说主要是完成一个可伸缩性(不确定的类型,以及不确定的条件,条件的变动可能是持续增加修改的)的业务判断.比如说完成一个成就系统,管 ...

  4. 关于Spring Data JPA 多表查询 返回自定义Vo的问题记录

    这两天开了一个新项目,使用SpringBoot+SpringData,  刚做了一个小功能,都是一张表的操作没什么问题,今天设计到了两张表联查,两张表各取了几个字段,组合成了一个vo, 当我用原生sq ...

  5. HTML / CSS技巧 – 可滚动的 tbody(漂亮表格)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 从苏宁电器到卡巴斯基第15篇:我在苏宁电器当营业员 VII

    我们苹果的倒班制度 当年我在苏宁的时候,实行的是单休制度,而且只能选择在周一到周五其中的某一天,因为周六周日顾客比较多,是不允许休息的.尽管是单休,但并不表示我们在上班的时候每天都要完完整整地上八小时 ...

  7. hdu4908 中位数子串

    题意:       给你N个数字组成的数列,然后问你这里面有多少个是以M为中位数的子序列. 思路:       首先分四中简单的情况求        (1) 就是只有他自己的那种情况 那么sum+1 ...

  8. 子域名探测工具Aquatone的使用

    目录 Aquatone Aquatone的安装 Aquatone的使用 子域名爆破 端口扫描

  9. mongo中常用的命令

    命令使用mongo shell 执行 1.mongo中增加新字段 mongo shell 进入后执行use table选中要添加字段的库 db.getCollection('表名').update({ ...

  10. windows桌面图标及任务管理栏丢失

    背景环境: 卸载某些软件,如Auto CAD 2011 之后,会出现桌面图标和任务栏丢失的现象,某些重要文件没有保存或者不能注销及重启的动作 1:按组合键Ctrl+Shift+Esc,键调出任务管理器 ...