(0)摘要
# 课程链接
全新 django3 入门到项目实战(零基础学django、项目开发实践、大学毕业设计均可用)_哔哩哔哩_bilibili
# 课程内容
(1)5-5 订单-ajax删除(对话框)
(2)5-6 订单-编辑
(3)5-7 订单-对话框逻辑调整
(4)5-8 数据统计-柱状图
(5)5-9 数据统计-饼图和折线图
# 长风破浪会有时,直挂云帆济沧海
(1)5-5 订单-ajax删除(对话框)
# (1)删除功能(JS 的知识点!!!)
1)这里有两种方案来做,一种是我们点击了某条数据的删除键,那么前端将选中的数据的 id 值取出来放在某个地方,当点击确认删除后,系统再将这个 id 发给后台进行删除;还有一种就是定义一个全局变量,只要点击了删除,那么对应的 id 就好赋值给这个全局变量,当确认删除后,就将全局变量发给后台(这也是我们后面用的)。
由上面的方法二可知,我们定义了一个全局变量,那么点击了删除键后,所选数据的 id 就会赋值给这个全局变量,然后确认删除后,再将 id 值发送给后端。
2)前端代码。那么我们首先要对前端的编辑代码添加一下特有的属性,为了就是后续 js 能够索引到它。这里就只需要记住,不为什么。 那么特有属性,就是 uid="{{obj.id}}" ,相当于就是点击的那条数据的 id 值,即为 uid。
3)然后我们绑定一个点击事件,只要单击了这个删除按钮,就把它的 id 赋值给我们设置的全局变量(因为我们遵循的是第二种方法来做)。当然了,还有删除操作的点击事件的方法函数 formDeleteEvent() 、确认删除点击事件的方法函数 confirmDeleteEvent() ,如图所示。
4)首先我们来编写 formDeleteEvent() 的函数。流程是这样的,只要在某行点击了删除键,那么模态对话框就会显示出来,然后我们就将这行数据的 id 赋值给全局变量 DELETE_ID。那么我们如何知道是哪一个标签的呢,那就是使用 $(this) 方法,返回当前选中的标签对象,同时调用 attr() 方法,来获取 uid 的值。这种方式,我们只需要记住即可。
5)在弹出的模态对话框中,如果用户确认了删除,那么我们就要将全局变量获得的 uid 值,返回到后端,让后端执行相应的删除操作了。也就是调用我们的确认删除点击事件的方法函数 confirmDeleteEvent(),流程就是使用 ajax 将 uid 传到后台。但是在此之前,我们需要给 tr 标签也加一个 uid 属性,方便后续的删除操作。
6)确认删除的第一种方法,就是要配合上面的 tr 标签的属性来用。直接给出代码。格式可能有点不好看,但是这个方法比较麻烦,详细的注释在下面了。这个主要是拿来学习下 js 的用法而已。
function confirmDeleteEvent() { $("#confirmDelete").click(function () { $.ajax({ //其实是可以直接做字符串拼接的,如"/order/"+ DELETE_ID + "/delete/", //那么我们可以更简单点,如下: url: '/order/delete/', type: 'GET', //因为我们用的是 GET 请求,所以请求的时候,会将 url 自动拼接为: // 设 DELETE_ID=123,那么发送的时候是 /order/delete/?uid=123 data: { uid: DELETE_ID }, dataType: 'JSON', success: function (res) { if (res.status) { alert("删除成功"); $("#deleteModal").modal('hide'); /** 在页面中删除掉被删除的那行数据(之前只是在数据库中删除了) * $("tr") 索引的就是页面中的 tr 标签。然后我们索引具有删除 uid 的那个 tr 标签,执行删除操作, * 这里的$("tr[uid='" + DELETE_ID + "']") 是字符串拼接,其中 DELETE_ID 会自动转为 str 类型 * 设 Str1: "tr[uid='" * Str2: DELETE_ID * Str3: "']" , 那么上面的式子就是 $(Str1 + Str2 + Str3) * 删除的话就是执行 remove() 方法。即 * $("tr[uid='" + DELETE_ID + "']").remove(); * 【注意】 * 但是这种方法,存在问题。如果有分页数据,且执行删除后, * 后面页的数据可能没办法顶到当前页 */ $("tr[uid='" + DELETE_ID + "']").remove(); //全局变量置空 DELETE_ID = 0; }else{ //返回错误信息 alert(res.error) } } }) }) }
7)确认删除的方法二,这个是很简单的,就是我们执行删除,并且隐藏模态对话框后,直接自动刷新页面即可。
(2)5-6 订单-编辑
# (1)索引 id(这是初级写法)
1)其实编辑的索引 id 的逻辑是和删除的索引 id 逻辑是一样的。一样的设置特有属性,和 js 代码,这里我们直接上代码。
2)js 代码。基本逻辑就是,每次点击事件后,先清空原来模态对话框的数据,不然不同的数据间会冲突。找到选中的 id 值,然后通过 ajax 请求发送 id 值到后台,后台再将原始的数据传回前台,然后放入模态对话框,最后呈现给用户查阅。
function bindEditEvent(){ $(".btn-edit").click(function (){ //清空原来 input 的数据 $("#formAdd")[0].reset(); //找到选中的那行数据的 id DELETE_ID = $(this).attr("uid") //ajax 的请求 $.ajax({ url: '/order/edit/', type: 'GET', data: { uid: DELETE_ID }, dataType: "JSON", success: function (res){ if (res.status){ //循环返回的数据 $.each(res.data, function (name, key) { $("#id_" + name).val(key) }) }else{ alert("编辑错误") } } }) //改一下抬头 $("#myModalLabel").text("编 辑"); //显示模态对话框 $('#myModal').modal('show'); }) }
3)视图函数的代码如下,更详细注释见后面的图示。
def order_edit(request): uid = request.GET.get("uid") """ 从数据库中取数据,返回的类型: (1) row_object = models.Order.objects.filter(pk=uid).first(), # row_object 是一个对象。取数据的话,比如 title 属性。 # 获取数据可以 row_object.title 就是点属性的方法。 # 但是这种查询方式是返回对象,无法以 Json 格式为序列化数据返回。 (2) row_list = models.Order.objects.filter(pk=uid).values("title", "price", "status").first() # 还有一种方法。但其实也可以是使用 .values() 方法, # 这样子返回的是一个字典,即 row_list = {'title': '电视', 'price': 1231232, 'status': 2} (3) row = models.Order.objects.all() # 返回的是一个对象查询集合, 即 <QuerySet [<Order: Order object (4)>, ...], 每一个对象都是一条数据 # 可以通过 row[0].title 来第一条数据的属性值 (4) row = models.Order.objects.all().values("title", "price") # 这里我们指定了特定的值,那么返回的就是一个字典查询集合,即 [{}, {}, ...], 每一个 {} 是一条数据。 # 事实上输出例如:<QuerySet [{'title': '手机', 'price': 12312}, {'title': '1231', 'price': 2131}, ...]> (5) row = models.Order.objects.all().values_list("title", "price") # 这里返回的是元组查询集。就是 [(), (), ...] , 每一个 () 是一条数据, # 里面元素的个数取决于我们给的 values_list("a", "b", "c", ...) 括号里面的字段个数。 # 比如我们只给了两个属性,那么就是这样的 <QuerySet [('手机', 12312), ('1231', 2131), ...] """ # 这里我们用上面的第 (2) 种方法 row_list = models.Order.objects.filter(pk=uid).values("title", "price", "status").first() if not row_list: ret = { "code": 1002, "status": False } return JsonResponse(ret) # 查询成功的话,返回相应的数据 ret = { "code": 1000, "status": True, "data": row_list } return JsonResponse(ret)
4)数据库的查询复习。
5)之所以说这个是因为 json 能返回的数据类型只能局限于基本的数据类型,如下图所示。
(3)5-7 订单-对话框逻辑调整
# (1)完善流程。
1)如果按照上述的方法来做的话,我们点击保存的时候,就会直接变成新建多一条数据。这是因为我们的新建和编辑的模态对话框是共用的。我们可以加入一个全局变量用来判断,我们的操作是新建还是编辑。下面是 js 代码,同时,我们要把编辑的事件的变量也给改了。【补充一下,如果一个变量为 undefined,那么转换为 boolean 类型的话,就是 False,基于这个思想来判断是新建还是编辑】
2)以下是编辑部分的完整 js 代码。
//修改后的代码 function formAddEvent() { $("#btnSave").click(function () { $(".error-msg").empty() if (EDIT_ID) { //编辑 $.ajax({ url: '/order/edit/save/' + "?uid=" + EDIT_ID, type: "post", data: $("#formAdd").serialize(), dataType: "JSON", success: function (res) { if (res.status) { alert("编辑成功") //保存成功后,清空表单。 // 因为jQuery 没有置空的功能,因此通过$("#formAdd")[0] 来绑定一个 DOM 对象 // 调用 .reset() 方法就可以将输入框给置空了。 $("#formAdd")[0].reset(); //保存成功后自动关闭 $("#myModal").modal('hide'); //保存成功后,页面自动刷新的方法。 location.reload(); } else { if (res.err_msg) { alert(res.err_msg) console.log(res.status) } else { $.each(res.error, function (name, err) { $("#id_" + name).next().text(err[0]) }) } } } }) } else { $.ajax({ url: '/order/add/', type: "post", data: $("#formAdd").serialize(), dataType: "JSON", success: function (res) { if (res.status) { alert("保存成功") //保存成功后,清空表单。 // 因为jQuery 没有置空的功能,因此通过$("#formAdd")[0] 来绑定一个 DOM 对象 // 调用 .reset() 方法就可以将输入框给置空了。 $("#formAdd")[0].reset(); //保存成功后自动关闭 $("#myModal").modal('hide'); //保存成功后,页面自动刷新的方法。 location.reload(); } else { $.each(res.error, function (name, err) { {#console.log(name, err)#} $("#id_" + name).next().text(err[0]) }) } } }) } }) }
3)我们编辑保存的视图函数如下:
(4)5-8 数据统计-柱状图
# (1)画图的第三方库
1)当前主要使用的画图库有两种,一个是国外的 highcharts,还有一个是国内 echarts,这节武sir 主要是以 echarts 为例讲的。
2)echarts 的基本使用。打开链接:Handbook - Apache ECharts ,我们可以看到如下的界面,选择通过 jsDelevr CDN 来下载。
使用 CDN 下载的时候,我们能来到如下界面,然后直接点红框的下载。下载的是一个类似于 demo 的压缩文件,我们只需要解压找到 /dist/echarts.min.js 即可。然后讲这个 js 文件放在我们 django 项目的 static/js/ 文件夹下即可。CDN 直通车:echarts CDN by jsDelivr - A CDN for npm and GitHub
3)然后我们直接就配置一个简单的路由和前端页面,来使用 echarts 官方给的示例代码,绘制一个柱状图。当然在此之前我们需要做一个是具有 id = bar ,带有长宽的 div 标签。
显示的结果如图:
# (2)示例代码的数据配置(本节主要是自己写的)
这一节主要借助文档来查阅和调试查看,我们只需要知道基本使用,后续根据需要到文档中查阅即可,文档链接: Documentation - Apache ECharts
1)title 的配置。 title 放的是一个字典(注意是 js 的),那格式就是 title: {}。比如下面的例子,我们给常用的一些属性写了备注。更多的可以参考文档。
结果如下图所示:
2)legend 的配置。这个是配置数据标识的。直接上代码看:
那么更直观的就是,显然 data 就是数据标识的名称。
3)xAxis 就是表的横轴,更多的可以查看文档来使用。 yAxis 说的就是纵轴,这个基本都是查阅文档来做
如图所示:
4)series 就是放数据的,我们放了两条数据进去。如下图所示,
那么最后的结果如下:
【总之,要用的时候,直接去查阅文档】
# (3)请求数据的方式来绘制柱状图
1)模拟请求数据,然后自动绘制。首先是 js 的代码。
<script type="text/javascript"> $(function () { paintBar(); }) function paintBar() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('bar')); //bar 图专用 var option = { color: [], title: {}, tooltip: {}, legend: { data: [], bottom: 0 }, xAxis: { data: [] }, yAxis: {}, series: [] } $.ajax({ url: '/charts/bar/', type: 'get', dataType: 'JSON', success: function (res) { if (res.status) { option.color = res.color; option.title = res.title option.legend.data = res.title.data option.xAxis.data = res.xAxis.data option.series = res.series //显示 myChart.setOption(option); } }, }) } </script>
2)后端的视图函数:
def charts_bar(request): ret = { "status": True, "color": ["#CC0033", "#3398DB"], "title": { "text": 'ECharts', "subtext": "子标题", "left": "20%", "textStyle": { "s": 30 } }, "legend": { "data": ['销量', "啥也不是"], "bottom": "0%" }, "xAxis": { "data": ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, "series": [ { "name": '销量', "type": 'bar', "data": [5, 20, 36, 10, 10, 20] }, { "name": '啥也不是', "type": 'bar', "data": [5, 20, 36, 10, 10, 20] } ] } return JsonResponse(ret)
【总之,多看 echarts 的文档,并且注意返回数据的格式。】
(5)5-9 数据统计-饼图和折线图
# 链接~~~有空再看了。主要是结合文档一起学。
全新 django3 入门到项目实战(零基础学django、项目开发实践、大学毕业设计均可用)_哔哩哔哩_bilibili