AJAX准备的知识:JSON
JSON指的是JavaScript对象表示法,也是轻量级的文本数据交换的格式
并且独立于语言,具有自我描述性,更易理解。
注意:JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
python与JS之间用json数据之间的转换:

合格的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的介绍
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用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
}
}
});
AJAX请求如何设置csrf_token
第一种是通过获取隐藏的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是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
==================================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插件示例

$(".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")
}
}
})
});
})