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');

 

 

 

 

posted @ 2020-06-05 15:32  徐之乔  阅读(123)  评论(0)    收藏  举报