1.Django与Ajax
AJAX简介(异步提交 局部刷新)
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。通过使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX不是新的编程语言,而是一种使用现有标准的新方法(比较装饰器)。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)。
Ajax我们只学习jQuery封装之后的版本(不学原生的 原生的复杂并且在实际项目中也一般不用),所以我们在前端页面使用ajax的时候需要确保导入了jQuery。ps:并不只有jQuery能够实现ajax,其他的框架也可以。
朝服务端发送请求的方式
# 1、浏览器地址栏直接输入url回车 GET请求 # 2、a标签href属性 GET请求 # 3、form表单 GET请求/POST请求 # 4、ajax GET请求/POST请求
案例
页面上有三个input框
在前两个框中输入数字 点击按钮 朝后端发送ajax请求
后端计算出结果 再返回给前端动态展示的到第三个input框中
(整个过程页面不准有刷新,也不能在前端计算)
<!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> </head> <body> <input type="text" id="d1">+ <input type="text" id="d2">= <input type="text" id="d3"> <p> <button id="btn">点我</button> </p> <script> // 先给按钮绑定一个点击事件 $('#btn').click(function(){ // 超后端发送ajax请求 $.ajax({ // 1.指定朝那个后端发送ajax请求 url:'', // 不写就是朝当前地址提交 // 2.请求方式 type:'post', // 不指定默认就是get请求,都是小写 // 3.数据 {#data:{'username':'jiang','password':123},#} data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 4.回调函数:当后端给你返回结果的时候会自动触发,args接收后端的返回结果 success:function (args) { alert(args) $('#d3').val(args) // 通过DOM操作动态渲染到第三个input框里面 {#$('#d3').val(args.outcome) #} console.log(typeof args) // js语法,查看args的数据类型 } }) }) </script> </body> </html>
from django.shortcuts import render,HttpResponse import json from django.http import JsonResponse def ab_ajax(request): if request.method == 'POST': print(request.POST) # <QueryDict: {'i1': ['1'], 'i2': ['2']}> i1 = request.POST.get('i1') # <class 'str'> i2 = request.POST.get('i2') # <class 'str'> # 先转成整形再相加 i3 = int(i1) + int(i2) d = {'code': i1, 'msg': i2, 'outcome':i3} # return HttpResponse(i3) # 前端args为string类型 # return HttpResponse(json.dumps(d)) # 前端args为string类型 return JsonResponse(d) # # 前端args为object类型(前端可以利用对象点属性来获取值) return render(request,'ab_ajax.html')
''' 针对后端如果是用HttpResponse返回的数据 回调函数不会自动帮你反序列化 如果后端直接用的是JsonResponse返回的数据 回调函数会自动帮你反序列化 HttpResponse解决方式 1.自己在前端利用JSON.parse() 2.在ajax里面配置一个dataType参数(dataType:'JSON') '''
前后端传输数据的编码格式(contentType)
主要研究post请求数据的编码格式
前后端传输数据的编码格式
# urlencoded # formdata # json
form表单数据传输格式
<body> <form action="" method="post"> <form action="" method="post" enctype="multipart/form-data"> <p>username: <input type="text" name="username" class="form-control"></p> <p>password: <input type="text" name="password" class="form-control"></p> <p>file: <input type="file" name="file"></p> <input type="submit" class="btn btn-success"> </form> </body>
def index(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return render(request,'index.html')
默认的数据编码格式是urlencoded 数据格式:username=jiang&password=12345 django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中 username=jiang&password=12345&file=%E8%BF%9E%E8%A1%A8%E6%9F%A5%E8%AF%A2.md >>> request.POST 如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中而将文件解析到request.FILES中 urlencodes <QueryDict: {'username': ['jiang'], 'password': ['12345'], 'file': ['连表查询.md']}>
formdata <QueryDict: {'username': ['jiang'], 'password': ['12345']}>
<MultiValueDict: {'file': [<InMemoryUploadedFile: 连表查询.md (application/octet-stream)>]}>
form表单是没有办法发送json格式数据的
ajax数据传输格式
<button id="btn">点我</button> <script> $('#btn').click(function(){ $.ajax({ url:'', type:'post', data:{'username':'jiang','age':20}, success:function(args){ } }) }) </script>
def index(request): if request.method == 'POST': print(request.POST) print(request.FILES) return render(request,'index.html')
默认的编码格式也是urlencoded 数据格式:username=jiang&age=20 django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
ajax发送数据
ajax发送json格式的数据
<body> <button id="d1">点我</button> <script> $('#d1').click(function(){ $.ajax({ url:'', type:'post', data:JSON.stringify({'username':'jiang','age':18}), contentType:'application/json', // 指定编码格式 success:function(args){ } }) }) </script> </body>
import json def ab_json(request): if request.is_ajax(): print(request.body) # b'{"username":"jiang","age":18}' # 针对json格式的数据需要自己手动处理 json_bytes = request.body # json_str = json_bytes.decode('utf-8') # json_dict = json.loads(json_str) # json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化 json_dict = json.loads(json_bytes) print(json_dict, type(json_dict)) # {'username': 'jiang', 'age': 18} <class 'dict'> return render(request,'ab_json.html')
''' 前后端传输数据时一定要确保编码格式跟数据真正的格式一致 data:JSON.stringify({'username':'jiang','age':18}), contentType:'application/json', // 指定编码格式 django针对json格式的数据 不会做任何的处理 request.is_ajax() 判断当前请求是否是ajax请求 返回布尔值 ajax发送json格式数据需要注意点 1.contentType参数指定成:application/json 2.数据是真正的json格式数据 3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理 '''
ajax发送文件
ajax发送文件需要借助js内置对象FormData
<body> <p>username:<input type="text" id="d1"></p> <p>password:<input type="text" id="d2"></p> <p><input type="file" id="d3"></p> <button id="d4">点我</button> <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> </body>
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 // 2 添加普通的键值对 formDateObj.append('username',$('#d1').val()); formDateObj.append('password',$('#d2').val()); // 3 添加文件对象 formDateObj.append('myfile',$('#d3')[0].files[0]) 2.需要指定两个关键性的参数 contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象 processData:false, // 告诉你的浏览器不要对你的数据进行任何处理 3.django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中 """
django自带的序列化组件
# 需求:在前端获取到后端用户表里面的所有数据,并且要求是列表套字典格式 [ {"pk": 1, "username": "yuan", "age": 20, "gender": "male"}, {"pk": 2, "username": "jiang", "age": 27, "gender": "male"}, {"pk": 3, "username": "yue", "age": 28, "gender": "female"}, {"pk": 4, "username": "wu", "age": 36, "gender": "others"} ] # 前后端分离的项目 作为后端只需要写代码将数据处理好 能够序列化返回给前端即可 再写一个接口文档,告诉前端每个字段代表的意思即可 [ {"model": "app01.user", "pk": 1, "fields": {"username": "yuan", "age": 20, "gender": 1}}, {"model": "app01.user", "pk": 2, "fields": {"username": "jiang", "age": 27, "gender": 1}}, {"model": "app01.user", "pk": 3, "fields": {"username": "yue", "age": 28, "gender": 2}}, {"model": "app01.user", "pk": 4, "fields": {"username": "wu", "age": 36, "gender": 3}} ] 写接口就是利用序列化组件渲染数据然后写一个接口文档
from app01 import models 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) # ab_ser.html <body> <p>{{ user_list }}</p> </body>
ajax结合sweetalert
from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ # ajax结合sweetalert re_path(r'^user/list/',views.user_list), re_path(r'^delete/user/',views.delete_user), ]
<!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 }}" id="d10">删除</button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.del').on('click',function (){ {#alert($(this).attr('delete_id'))#} // 先将当前标签对象存储起来 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('deleted_id'), // 传递主键值方式一#} url:'delete/user', // 传递主键值方式二,放在请求体里面 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 from django.http import JsonResponse 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)