AJAX AJAX请求如何设置csrf_token AJAX上传文件 同源策略与Jsonp CORS 补充一个SweetAlert插件示例

AJAX准备的知识:JSON

JSON指的是JavaScript对象表示法,也是轻量级的文本数据交换的格式

并且独立于语言,具有自我描述性,更易理解。

注意:JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。

python与JS之间用json数据之间的转换:

AJAX
AJAX请求如何设置csrf_token
AJAX上传文件
同源策略与Jsonp
CORS
补充一个SweetAlert插件示例

合格的JSON格式的对象:

["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["张三", "李四"] }
[ { "name": "张三"}, {"name": "李四"} ] 

  

不合格的JSON格式的对象:

{ name: "张三", 'age': 32 }  ,{ "name": 张三, 'age': 32 }// 属性名和后面的值必须使用双引号
[32, 64, 128, 0xFFF] // 不能使用十六进制值
{ "name": "张三", "age": undefined }  // 不能使用undefined
{ "name": "张三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}  // 不能使用函数和日期对象
}

 

XML和JSON都使用结构化方法来标记数据,只不过JSON 格式有两个显著的优点:1.书写简单,一目了然;

2.符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。

AJAX的介绍

AJAXAsynchronous Javascript And XML)翻译成中文就是异步的JavascriptXML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程,即局部的刷新

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

AJAX的应用场景:

我们前端往后端发请求的方式:
     1. 直接在地址栏输入URL
     2. a标签
     3. form表单
     4. AJAX

HTTP请求的类型:
GET
POST

 AJAX特点:

 1. 异步
 2. 局部刷新(偷偷发请求)

AJAX缺点:
 请求零碎,滥用对服务端压力大

 

用jQuery封装的ajax方法:

$("#b1").on("click", function () {
    // 点击 id是b1的按钮要做的事儿
      var i1 = $("#t1").val();
      var i2 = $("#t2").val();
      // 往后端发数据
      $.ajax({
          url: "/ajax_demo/",
          type: "get",
          data: {"t1": i1, "t2": i2},
          success: function (arg) {
              {#alert(arg);#}
              // 把返回的结果填充到 id是i3的input框中
              $("#t3").val(arg);
          }
      })
  });

$.ajax的参数

data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。用json将数据类型转变为字符串传递给后端。

$("#b1").on("click", function () {
    $.ajax({
      url:"/ajax_add/",
      type:"GET",
      datatype:"json"    
      data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
      success:function (data) {
        $("#i3").val(data);
      }
    })
  })

datatype: "josn",是帮你把数据封装为json格式的字符串,然后传递给视图函数;
JsonResponse 多了一个请求头:'content_type'
:视图函数返回的数据转为json字符串,只是在ajax接收函数返回的数据的时候自己帮你反序列为object对象了
而 HttpResponse 也是将视图函数返回的数据转为json字符串,但是在ajax接收函数返回的数据的时候需要自己反序列化(json.parse)

from django.http import JsonResponse 
               user = auth.authenticate(username=username, password=pwd)
            if user:
                # 用户名密码正确
                # 给用户做登录
                auth.login(request, user)
                ret["msg"] = "/index/"
            else:
                # 用户名密码错误
                ret["status"] = 1
                ret["msg"] = "用户名或密码错误!"
        else:
            ret["status"] = 1
            ret["msg"] = "验证码错误"

        return JsonResponse(ret)

HTML中:

            $.ajax({
                url: "/login/", // 进行二次验证
                type: "post",
                dataType: "json",
                data: {
                    username: $('#inputName3').val(),
                    password: $('#inputPassword3').val(),
                    geetest_challenge: validate.geetest_challenge,
                    geetest_validate: validate.geetest_validate,
                    geetest_seccode: validate.geetest_seccode
                },
                success: function (data) {
                    if (data.status) {
                        $(".login-error").text(data.msg)
                    } else {
                        location.href = data.msg
                    }
                }
            });

  

第一种是通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。 

{% csrf_token %}


<script>
$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  data: {
    "username": "Q1mi",
    "password": 123456,
    "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
  },
  success: function (data) {
    console.log(data);
  }
})
</script>

第二种是自己写插件,把通过获取返回的cookie中的字符串 放置在请求头中发送。

只需要导入js即可以。

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

  

AJAX的请求的参数

######################------------data---------################

       data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式
             (urlencoded:?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会对数据进行深层次迭代;
request.body是前端传过来的数据。
如果是contentType:"application/json"的类型的,取数据要从request.body取。request.body=b'{"name":"a"}'。
json.loads(request.body.decode("utf8"))

如果是默认的processData,则request.body为b'name=a',默认的帮你把数据按照键值对的形式封装到request.POST里面。

name = request.POST.get("name")

  

 

AJAX上传文件

和表单上传文件的意思差不多,对于表单来说,传文件需要添加这一属性

enctype="multipart/form-data"

 

而对于ajax来说的话:

// 上传文件示例
$("#b3").click(function () {
  var formData = new FormData();
  formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
  formData.append("f1", $("#f1")[0].files[0]);
  $.ajax({
    url: "/upload/",
    type: "POST",
    processData: false,  // 告诉jQuery不要去处理发送的数据
    contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
    data: formData,
    success:function (data) {
      console.log(data)
    }
  })
})

  

 

补充:跨域请求

同源策略与Jsonp

同源策略:

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
==================================http://127.0.0.1:8001项目的index
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>


<button>ajax</button>
{% csrf_token %}

<script>
    $("button").click(function(){


        $.ajax({
            url:"http://127.0.0.1:7766/SendAjax/",
            type:"POST",
            data:{"username":"yuan","csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()},
            success:function(data){
                alert(123);
                alert(data)
            }
        })
    })
</script>
</body>
</html>


==================================http://127.0.0.1:8001项目的views

def index(request):


    return render(request,"index.html")


def ajax(request):
    import json
    print(request.POST,"+++++++++++")
    return HttpResponse(json.dumps("hello"))

  

 上面的示例因为不满足同源的要求,则执行这个项目的时候会报错,

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:7766/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

说明是浏览器对非同源请求返回的结果做了拦截。  

jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

<script src="http://127.0.0.1:8008/books/?func=func_name"></script>

  这样的形式虽然能进行跨域,但是返回是一个变量,没有意义,做改进就是返回一个函数,把数据(必须是字符串,如果不是字符串的话就在前端报没有定义的错误)放入函数里面,通过调用函数能得到数据。

def books(request):   #基于jsonp
	funcname = request.GET.get("callbacks")
	data = {"name":"alex","age":32}
	return HttpResponse("%s('%s')"%(funcname,json.dumps(data)))
<script>
    function alex(arg){
       console.log(arg)
    }
    </script>

 这样可以实现功能,但是不够灵活,因为代码一执行就进跨域了,因此才用伪造的ajax来实现跨域。

模板中;

 $(".btn").on("click", function () {
        $.ajax({
                url: "http://127.0.0.1:8008/books/",
                type: "get",
                dataType: "jsonp",    //伪造的ajax , 跨域请求,但是本质上还是基于script 上面的原理;
                jsonp: "callbacks",   //k值 , v值(函数名)一般不写,是随机的生成的,即函数名不用自己取;
                //jsonpCallback:"V值",
                success: function (arg) {       //就相当于上面的函数,arg 就是跨域得到的数据。
                    var data = JSON.parse(arg);  //反序列化#}
                    console.log(typeof data);
                    console.log(data)
                }
            }
        )
    })

视图中:

import json

# def books(request):   #基于jsonp
# 	funcname = request.GET.get("callbacks")
# 	data = {"name":"alex","age":32}
# 	return HttpResponse("%s('%s')"%(funcname,json.dumps(data)))

  

  

从原因:CORS 头缺少 'Access-Control-Allow-Origin',可以看出还有一种跨域请求的。

CORS

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

 

  //8000端口的   
// 基于cors实现跨域请求 $.ajax({ url: "http://127.0.0.1:8008/books/", type: "get", success: function (arg) { console.log(arg) } }) ;

  

def books(request):  # 基于cors实现跨域请求
	data = {"name":"alex","age":32}
	response = HttpResponse(json.dumps(data))
	# response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000"#(访问的地址)  #加到cors头上,即当时这个域名访问的时候就可以拿数据了
	response["Access-Control-Allow-Origin"] = "*"  #所有的域名访问都可以
	return response

  

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

  

  

补充一个SweetAlert插件示例

AJAX
AJAX请求如何设置csrf_token
AJAX上传文件
同源策略与Jsonp
CORS
补充一个SweetAlert插件示例

$(".btn-danger").on("click", function () {
  swal({
    title: "你确定要删除吗?",
    text: "删除可就找不回来了哦!",
    type: "warning",
    showCancelButton: true,
    confirmButtonClass: "btn-danger",
    confirmButtonText: "删除",
    cancelButtonText: "取消",
    closeOnConfirm: false
    },
    function () {
      var deleteId = $(this).parent().parent().attr("data_id");
      $.ajax({
        url: "/delete_book/",
        type: "post",
        data: {"id": deleteId},
        success: function (data) {
          if (data.status === 1) {
            swal("删除成功!", "你可以准备跑路了!", "success");
          } else {
            swal("删除失败", "你可以再尝试一下!", "error")
          }
        }
      })
    });
})