Ajax基本操作
$.ajax({
url:“/index/”,
type:"get","post",
data:,{key:value}其中value不能是字典,只能是数组,字符串,数字;$("").serilizer()
dataType:,"json","text(默认)","html","xml"
traditional:true,#传select多值,列表[2,3,5,4]
success:function(arg){
},
error:function(){
},
})
一、post请求CSRFToken验证
弹出Forbidden
解决办法:1、避过去
1 需要在views.py里要出发post请求的函数前加入@csrf_exempt ,之前要引入from django.views.decorators.csrf import csrf_exempt 2 在 settings.py 中 MIDDLEWARE_CLASSES 中 注释掉'django.middleware.csrf.CsrfViewMiddleware'
2、解决
<form action=""> {% csrf_token %} <input type="button"value="点我"class="btn"> </form>
from django.http import JsonResponse from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def index(request): if request.method=="POST": print(request.POST.get("username")) return JsonResponse({'status':"ok"}) else: return render(request,"index.html")
$.ajax({ url:"{% url 'index' %}", type:"post", contentType:"application/json", data:{ username:"wusan", csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), }, success:function (arg) { console.log(arg); } })
二、data数据类型,允许的数据类型为数组,数字,字符串
1、如果要传数组(select多选标签)
dataType:'json'指定后,arg就是json 对象,可以直接点arg.status
如果此处不指定dataType为json,则arg为字符串,需要用JSON.parse(arg)转换
traditional:true,
$.ajax({ url:"{% url 'index' %}", type:"get", traditional:true, data:{data:[1,2,3]},
dataTYpe:'json', success:function (arg) { console.log(arg); } })
后端获取:
data=request.POST.getlist("data") print(data)
2、传字典类型(js没有字典类型,统一看做object)将字典用JSON.stringify()函数转字符串传递
var data={"name":'王五',"age":18}
$.ajax({
url:"{% url 'index' %}",
type:"get",
traditional:true,
data:{data:JSON.stringify(data)},
success:function (arg) {
console.log(arg);
}
})
3、使用formData封装数据如字典类型;一半用formData上传文件
######################------------data---------################ data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式 (urlencode:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。 function testData() { $.ajax("/test",{ //此时的data是一个json形式的对象 data:{ a:1, b:2 } }); //?a=1&b=2 ######################------------processData---------################ processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false, 那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString() ,最后得到一个[object,Object]形式的结果。 ######################------------contentType---------################ contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。 用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据, 比如contentType:"application/json",即向服务器发送一个json字符串: $.ajax("/ajax_get",{ data:JSON.stringify({ a:22, b:33 }), contentType:"application/json", type:"POST", }); //{a: 22, b: 33} 注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象 views.py: json.loads(request.body.decode("utf8")) ######################------------traditional---------################ traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]}, traditional为false会对数据进行深层次迭代;
processData:false,
contentType:false,
var data=new FormData(); data.append('k1','v1'); data.append('k2','v2'); $.ajax({ url:'/ajax1.html', type:'post', data:data, success:function (arg) { console.log(arg); }, processData:false, contentType:false, })
三、上传文件;使用formData封装
注意:由于 FormData 是 XMLHttpRequest Level 2 新增的接口,现在 低于IE10 的IE浏览器不支持 FormData。
<form > {% csrftoken%} <input name="user" type="text" id="user"/> <input type="file" name="avatar_img"/> <button type="button" id="ajax-submit" value="上传"> </form>
$("#ajax-submit").click(function(){ var formdata=new FormData(); #ajax上传文件的时候,需要这个类型,它会将添加给它的键值对加工成formdata的类型 formdata.append("user",$("#user").val()); #添加键值的方法是append,注意写法,键和值之间是逗号 formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); #别忘了csrf_token #formdata.append("avatar_img",$("#avatar")[0].files[0]); formdata.append("avatar_img",document.getElementById("avatar").files[0]); $.ajax({ url:"", type:"post", data:formdata, #将添加好数据的formdata放到data这里 processData: false , // 不处理数据 contentType: false, // 不设置内容类型 success:function(data){ console.log(data) } }) })
后端类似下面代码
from django import forms from django.forms import fields class UploadForm(forms.Form): user=fields.CharField() img=fields.FileField() # Create your views here. def upload(request): if request.method=="GET": return render(request,"upload.html") else: obj=UploadForm(request.POST,request.FILES) #img是一个对象(大小,名称,内容...) if obj.is_valid(): user=obj.cleaned_data["user"] img=obj.cleaned_data["img"] path="static\\"+img.name f=open(path,"wb") for line in img.chunks(): f.write(line) f.close() return HttpResponse("ok")
下载文件:
<div>
<a href="{% url 'download' %}">文件下载</a>
</div>
urlpatterns = [ url(r'^index/', views.index,name='index'), url(r'^download/', views.download,name='download'), ]
后台下载有三种方式:1、
from django.shortcuts import HttpResponse def download(request): file = open('crm/models.py', 'rb') #打开指定的文件 response = HttpResponse(file) #将文件句柄给HttpResponse对象 response['Content-Type'] = 'application/octet-stream' #设置头信息,告诉浏览器这是个文件 response['Content-Disposition'] = 'attachment;filename="models.py"' #这是文件的简单描述,注意写法就是这个固定的写法 return response
2、
from django.http import StreamingHttpResponse # def download(request): file=open('crm/models.py','rb') response =StreamingHttpResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
3、
from django.http import FileResponse def download(request): file=open('crm/models.py','rb') response =FileResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
推荐使用第三种
四、跨域
1、CORS
简单请求:
function submitJsonp2() { $.ajax({ url:"http://127.0.0.1:8090/xiaokai.html", type:"get", dataType: 'text', success: function(data, statusText, xmlHttpRequest){ console.log(data); } }) } def xiaokai(request): ret= HttpResponse(".....") #设置header #*为允许所有地址 #ret['Access-Control-Allow-Origin']='*' ret['Access-Control-Allow-Origin']=“http://127.0.0.1:8090,http://127.0.0.1:8080,...” return ret
复杂请求:contentType为application/json,和...
前端报错:Access-Control-Allow-Headers,页面的响应Request-method为Options
解决:
from django.shortcuts import render from django.http import JsonResponse # Create your views here. def books(request): # return JsonResponse(['西游记2','三国演义2','水浒传2'],safe=False) obj = JsonResponse(['西游记2','三国演义2','水浒传2'],safe=False) # obj["Access-Control-Allow-Origin"] = "*" obj["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000" print(request.method) #处理预检的options请求,这个预检的响应,我们需要在响应头里面加上下面的内容 if request.method == 'OPTIONS': # obj['Access-Control-Allow-Headers'] = "Content-Type" #"Content-Type",首字母小写也行 # obj['Access-Control-Allow-Headers'] = "content-type" #"Content-Type",首字母小写也行。这个content-type的意思是,什么样的请求体类型数据都可以,我们前面说了content-type等于application/json时,是复杂请求,复杂请求先进行预检,预检的响应中我们加上这个,就是告诉浏览器,不要拦截 obj['Access-Control-Allow-Headers'] = "content-type,b" #发送来的请求里面的请求头里面的内容可以定义多个,后端需要将头配置上才能访问 return obj
附:
* 简单请求 OR 非简单请求 条件: 1、请求方式:HEAD、GET、POST 2、请求头信息: Accept Accept-Language Content-Language Last-Event-ID Content-Type 对应的值是以下三个中的任意一个 application/x-www-form-urlencoded multipart/form-data text/plain 注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
2、JSONP,解决跨域问题
注意:JSONP只能发GET请求
function submitJsonp2() { $.ajax({ url:"http://127.0.0.1:8090/xiaokai.html", type:"get", dataType:"jsonp", jsonp:'callback', jsonpCallback:'func', }) } function func(arg) { console.log(arg) } #、、、、、、、、、、、、 def xiaokai(request): return HttpResponse("func('我要上小云');")
五、Ajax的原生形式和伪AJax
1、伪AJax:Iframe+form
iframe的name于form的target一致
<h6>基于iframe+form表单</h6>
<iframe id="iframe" name="ifra"></iframe>
<form id="fm" action="/ajax1.html"method="post"target="ifra">
<input type="text"name="root"value="11111">
<!--<input type="submit"value="提交" >-->
<a onclick="AjaxSubmit5();"></a>
</form>
function AjaxSubmit5() { document.getElementById("iframe").onload=reloadIframe; document.getElementById("fm").submit(); }
function reloadIframe() { var iframetext=$(this).contents().find('body').html(); var obj=JSON.parse(iframetext); if(obj.status){ } }
注:
1、标签上绑定onload="reloadIframe(this);",reloadIframe函数里面的this=window,不为当前标签,需要传this 2、document.getElementById("").onclick=funcName1; function funcName1(){ this=当前标签 }
伪Ajax上传图片:
<iframe name="iframe1" id="iframe1" style="display:none;"></iframe>
<iframe name="iframe1" id="iframe1" style="display:none;"></iframe> <form action="/ajax1.html"method="post"target="iframe1" id="fm1" enctype="multipart/form-data"> <input type="file"id="img"name="k3"> <a onclick="submit8();">提交</a> </form>
function submit8() { document.getElementById("iframe1").onload=reloadSubmit1; document.getElementById("fm1").submit(); } function reloadSubmit1() { var text=this.contentWindow.document.body.innerHTML; var data=JSON.parse(text) console.log(data.message) }
2、原生ajax:XMLHttpRequest
XmlHttpRequest对象的主要方法:
a. void open(String method,String url,Boolen async)
用于创建请求
参数:
method: 请求方式(字符串类型),如:POST、GET、DELETE...
url: 要请求的地址(字符串类型)
async: 是否异步(布尔类型)
b. void send(String body)
用于发送请求
参数:
body: 要发送的数据(字符串类型)
c. void setRequestHeader(String header,String value)
用于设置请求头
参数:
header: 请求头的key(字符串类型)
vlaue: 请求头的value(字符串类型)
d. String getAllResponseHeaders()
获取所有响应头
返回值:
响应头数据(字符串类型)
e. String getResponseHeader(String header)
获取响应头中指定header的值
参数:
header: 响应头的key(字符串类型)
返回值:
响应头中指定的header对应的值
f. void abort()
终止请求
a. Number readyState 状态值(整数) 详细: 0-未初始化,尚未调用open()方法; 1-启动,调用了open()方法,未调用send()方法; 2-发送,已经调用了send()方法,未接收到响应; 3-接收,已经接收到部分响应数据; 4-完成,已经接收到全部响应数据; b. Function onreadystatechange 当readyState的值改变时自动触发执行其对应的函数(回调函数) c. String responseText 服务器返回的数据(字符串类型) d. XmlDocument responseXML 服务器返回的数据(Xml对象) e. Number states 状态码(整数),如:200、404... f. String statesText 状态文本(字符串),如:OK、NotFound...
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>XMLHttpRequest - Ajax请求</h1> <input type="button" onclick="XmlGetRequest();" value="Get发送请求" /> <input type="button" onclick="XmlPostRequest();" value="Post发送请求" /> <script src="/statics/jquery-1.12.4.js"></script> <script type="text/javascript"> function GetXHR(){ var xhr = null; if(XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } return xhr; } function XhrPostRequest(){ var xhr = GetXHR(); // 定义回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 已经接收到全部响应数据,执行以下操作 var data = xhr.responseText; console.log(data); } }; // 指定连接方式和地址----文件方式 xhr.open('POST', "/test/", true); // 设置请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); // 发送请求 xhr.send('n1=1;n2=2;'); } function XhrGetRequest(){ var xhr = GetXHR(); // 定义回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 已经接收到全部响应数据,执行以下操作 var data = xhr.responseText; console.log(data); } }; // 指定连接方式和地址----文件方式 xhr.open('get', "/test/", true); // 发送请求 xhr.send(); } </script> </body> </html>
post的请求必须要加请求头xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');


浙公网安备 33010602011771号