contentType
当我们使用form表单提交数据时,有一个enctype属性,默认情况下不写
此时我们提交数据时,会默认将数据以application/x-www-form-urlencoded的编码方式发送
该形式的数据为"k1=v1&k2=v2"格式,可以看成是一组组的键值对
但是当我们要发送图片等二进制文件时,上面的形式就无法实现了,此时我们会将enctype属性设置为form-data
这时我们就既可以发送键值对的数据,又可以发送较大的二进制文件了
同样,在使用ajax发送数据时,默认情况下,我们发送的get和post请求都是以application/x-www-form-urlencoded的编码方式发送的
但是我现在想要向后端发送一个json字符串形式的数据,该怎么办呢
这里我们就需要使用ajax里的contentType参数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> </head> <body> <button class="json_send">send</button> {% csrf_token %} <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $(".json_send").click(function () { $.ajax({ url:"/ajax_send/", data:JSON.stringify({"k1":"v1"}), type:"post", contentType:"application/json", success:function (data) { console.log(data) } }); </script>
如果以上面的形式直接发送,我们会发现后端接收时,request.POST和request.GET内都取不到值
def ajax_send(request): import json print(request.GET) # <QueryDict: {}> print(request.POST) # <QueryDict: {}> print(request.body.decode()) # {"k1":"v1"}return HttpResponse("OK")
这就要从帮助Django处理http请求的wsgiref模块说起了
该模块主要做了三件事:
1.封装了一个socket对象,通过该对象与客户端建立连接
2.按照http协议解析数据
3.按照http协议封装响应数据
当该模块解析数据时,会有一定的规则
wsgi: if content_type: url_encoded: request.body :post(get)数据-------> request.POST(GET)
当数据格式为application/x-www-form-urlencoded时,他会把数据写到request.POST或者request.GET中,如果为其它格式,则不会,此时我们如果想拿到数据必须从request.body中取
这样我们就完成了json字符串格式的数据发送,但是我们注意到这里我们发送的是post请求,但是却未带csrftoken的相关数据,如果通过中间件的话,这个请求会被拒绝,那我们该如何将csrftoken的值一起发送过去呢
这里我们先研究一下csrftoken的中间件是如何取相应的值的
CsrfViewMiddleware: if random_str=request.POST.get("csrfmiddlewaretoken") if random_str=="347289asd328": pass elif request.META.get("X-CSRFToken"): request.META.get("X-CSRFToken")=="asdasdh23470ahsd37sa" else: return Htttpresponse("forbidden error")
我们发现中间件会先从request.POST中取,但是我们的数据不会被放到request.POST中,所以取不到
这时中间件又会从请求头部的X-CSRFToken中取值,如果还取不到,那么会forbidden
所以我们此时就要想办法将csrftoken的值放到请求头的X-CSRFToken中
其实每当我们发送一次请求时,我们会发现在我们的COOKIE中也会带有csrftoken的相关内容,此时就从中取值放入X-CSRFToken中
<script src="{% static ‘js/jquery.cookie.js‘ %}"></script> // 必须要引用,不然无法使用$.cookie方法 $.ajax({ headers:{"X-CSRFToken":$.cookie(‘csrftoken‘)}, })
我们的代码为
$(".json_send").click(function () { $.ajax({ url:"/ajax_send/", data:JSON.stringify({"k1":"v1"}), type:"post", headers:{"X-CSRFToken":$()}, contentType:"application/json", success:function (data) { console.log(data) } });
dataType
该属性表示我们期待服务器发送回来的数据是一个什么类型
如:dataType:json,表示我们期待服务器端发送的是一个json格式的数据
这个属性并不会改变服务器端的内容,但是当客户端拿到服务器端的数据后,ajax方法会将数据进行parser操作,得到我们想要的类型
error和complete
$(".send_Ajax").click(function(){ $.ajax({ url:"/handle_Ajax/", type:"POST", data:{username:"Yuan",password:123}, success:function(data){ alert(data) }, //=================== error============ error: function (jqXHR, textStatus, err) { // jqXHR: jQuery增强的xhr // textStatus: 请求完成状态 // err: 底层通过throw抛出的异常对象,值与错误类型有关 console.log(arguments); }, //=================== complete============ complete: function (jqXHR, textStatus) { // jqXHR: jQuery增强的xhr // textStatus: 请求完成状态 success | error console.log(‘statusCode: %d, statusText: %s‘, jqXHR.status, jqXHR.statusText); console.log(‘textStatus: %s‘, textStatus); },
我们使用success回调函数是在执行不出错时执行的,如果执行过程中出了错误,则会执行error的回调函数,而complete是不管出不出错都会执行的