一 前后端传输数据的编码格式(contentType)
我们主要研究post请求数据的编码格式
get请求数据就是直接放在url后面的url?username=jason&password=123
可以朝后端发送post请求的方式:1.form表单 2.ajax请求
前后端传输数据的编码格式:urlencoded formdata json
研究form表单
默认的数据编码格式是urlencoded
数据格式:username=jason&password=123
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中,而将文件解析到request.FILES中
form表单是没有办法发送json格式数据的
研究ajax
默认的编码格式也是urlencoded
数据格式:username=jason&age=20
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
1.1 ajax发送json格式数据
前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的不要骗人家!!!
发送一个json数据(eg:{"username":"jason","age":25} )在request.POST里面肯定找不到,那么数据在哪里呢
django针对json格式的数据 不会做任何的处理 ,需要你自己去request.body获取并处理
#前端 <script> $('#d1').click(function () { $.ajax({ url:'', type:'post', data:JSON.stringify({'username':'jason','age':25}), contentType:'application/json', // 指定编码格式 success function () { } }) }) </script> #后端 if request.is_ajax(): 判断是否是ajax请求,返回布尔值 json_bytes = request.body # json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化 json_dict = json.loads(json_bytes) # {'username': 'jason', 'age': 25} <class 'dict'> return render(request,'ab_json.html')
ajax发送json格式数据需要注意点
1.contentType参数指定成:application/json
2.数据是真正的json格式数据
3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理
1.2 ajax发送文件
ajax发送文件需要借助于js内置对象FormData
#前端 <script> // 点击按钮朝后端发送普通键值对和文件数据 $('#d4').on('click',function () { // 1 需要先利用FormData内置对象 let formDateObj = new FormData(); // 2 添加普通的键值对 formDateObj.append('username',$('#d1').val()); formDateObj.append('password',$('#d2').val()); // 3 添加文件对象 formDateObj.append('myfile',$('#d3')[0].files[0]) // 4 将对象基于ajax发送给后端 $.ajax({ url:'', type:'post', data:formDateObj, // 直接将对象放在data后面即可 // ajax发送文件必须要指定的两个参数 contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象 processData:false, // 告诉你的浏览器不要对你的数据进行任何处理 success:function (args) { } }) }) </script> #后端 def ab_file(request): if request.is_ajax(): if request.method == 'POST': print(request.POST) print(request.FILES) return render(request,'ab_file.html')
总结:
1.需要利用内置对象FormData
1.2 添加普通的键值对
formDateObj.append('username',$('#d1').val()); formDateObj.append('password',$('#d2').val());
1.3 添加文件对象
formDateObj.append('myfile',$('#d3')[0].files[0])
2.需要指定两个关键性的参数
contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象
processData:false, // 告诉你的浏览器不要对你的数据进行任何处理
3.django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中
二 django自带的序列化组件(drf做铺垫)
需求:在前端给我获取到后端用户表里面所有的数据 并且要是列表套字典
import json from django.http import JsonResponse from django.core import serializers def ab_ser(request): user_queryset = models.User.objects.all() #不使用序列化 # [{},{},{},{},{}] # user_list = [] # for user_obj in user_queryset: # tmp = { # 'pk':user_obj.pk, # 'username':user_obj.username, # 'age':user_obj.age, # 'gender':user_obj.get_gender_display() # } # user_list.append(tmp) # return JsonResponse(user_list,safe=False) # 序列化 res = serializers.serialize('json',user_queryset) """会自动帮你将数据变成json格式的字符串 并且内部非常的全面""" return HttpResponse(res)
前后端分离的项目,作为后端开发的你只需要写代码将数据处理好,能够序列化返回给前端即可 ,再写一个接口文档 告诉前端每个字段代表的意思即可
写接口就是利用序列化组件渲染数据然后写一个接口文档 该交代交代一下就完事
三 ajax结合sweetalert
需求:实现删除时的二次确认
首先谁便在模板中copy一个下来放到前端页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <style> div.sweet-alert h2 { padding-top: 10px; } </style> {% load static %} <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}"> <script src="{% static 'dist/sweetalert.min.js' %}"></script> {# 关于静态文件查找 其实还有一个方法 代码发布再透露 #} </head> <body> <div class="container-fluid"> <h1 class="text-center">数据展示</h1> <div class="row"> <div class="col-md-8 col-md-offset-2"> <table class="table-striped table table-hover"> <thead> <tr> <th>ID</th> <th>username</th> <th>age</th> <th>gender</th> <th>actions</th> </tr> </thead> <tbody> {% for user_obj in user_queryset %} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.username }}</td> <td>{{ user_obj.age }}</td> <td>{{ user_obj.get_gender_display }}</td> <td> <button class="btn btn-primary btn-xs">编辑</button> <button class="btn btn-danger btn-xs del" delete_id="{{ user_obj.pk }}">删除</button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.del').on('click',function () { // 先将当前标签对象存储起来 let currentBtn = $(this); // 二次确认弹框 swal({ title: "你确定要删吗?", text: "你可要考虑清除哦,可能需要拎包跑路哦!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "是的,老子就要删!", cancelButtonText: "算了,算了!", closeOnConfirm: false, closeOnCancel: false, showLoaderOnConfirm: true }, function(isConfirm) { if (isConfirm) { // 朝后端发送ajax请求删除数据之后 再弹下面的提示框 $.ajax({ {#url:'/delete/user/' + currentBtn.attr('delete_id'), // 1 传递主键值方式1#} url:'/delete/user/', // 2 放在请求体里面 type:'post', data:{'delete_id':currentBtn.attr('delete_id')}, success:function (args) { // args = {'code':'','msg':''} // 判断响应状态码 然后做不同的处理 if(args.code === 1000){ swal("删了!", args.msg, "success"); // 1.lowb版本 直接刷新当前页面 {#window.location.reload()#} // 2.利用DOM操作 动态刷新 currentBtn.parent().parent().remove() }else{ swal('完了','出现了位置的错误','info') } } }) } else { swal("怂逼", "不要说我认识你", "error"); } }); }) </script> </body> </html>
后端返回数据和删除数据
def user_list(request): user_queryset = models.User.objects.all() return render(request,'user_list.html',locals()) import time def delete_user(request): """ 前后端在用ajax进行交互的时候 后端通常给ajax的回调函数返回一个字典格式的数据 :param request: :return: """ if request.is_ajax(): if request.method == 'POST': back_dic = {"code":1000,'msg':''} time.sleep(3) # 模拟操作数据的延迟 delete_id = request.POST.get('delete_id') models.User.objects.filter(pk=delete_id).delete() back_dic['msg'] = '数据已经删了,你赶紧跑路!' # 我们需要告诉前端我们操作的结果 return JsonResponse(back_dic)
四 批量插入
def ab_pl(request): # 先给Book插入一万条数据 # for i in range(10000): # models.Book.objects.create(title='第%s本书'%i) # # 再将所有的数据查询并展示到前端页面 book_queryset = models.Book.objects.all() # 批量插入 book_list = [] for i in range(100000): book_obj = models.Book(title='第%s本书'%i) book_list.append(book_obj) models.Book.objects.bulk_create(book_list) """ 当你想要批量插入数据的时候 使用orm给你提供的bulk_create能够大大的减少操作时间 """ return render(request,'ab_pl.html',locals())
五 分页器
""" 总数据100 每页展示10 需要10 总数据101 每页展示10 需要11 总数据99 每页展示10 需要10 如何通过代码动态的计算出到底需要多少页? 在制作页码个数的时候 一般情况下都是奇数个 符合中国人对称美的标准 """ # 分页 book_list = models.Book.objects.all() # 想访问哪一页 current_page = request.GET.get('page',1) # 如果获取不到当前页码 就展示第一页 # 数据类型转换 try: current_page = int(current_page) except Exception: current_page = 1 # 每页展示多少条 per_page_num = 10 # 起始位置 start_page = (current_page - 1) * per_page_num # 终止位置 end_page = current_page * per_page_num # 计算出到底需要多少页 all_count = book_list.count() page_count, more = divmod(all_count, per_page_num) if more: page_count += 1 page_html = '' xxx = current_page if current_page < 6: current_page = 6 for i in range(current_page-5,current_page+6): if xxx == i: page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i) else: page_html += '<li><a href="?page=%s">%s</a></li>'%(i,i) book_queryset = book_list[start_page:end_page] """ django中有自带的分页器模块 但是书写起来很麻烦并且功能太简单 所以我们自己想法和设法的写自定义分页器 上述推导代码你无需掌握 只需要知道内部逻辑即可 我们基于上述的思路 已经封装好了我们自己的自定义分页器 之后需要使用直接拷贝即可 """