Ajax
同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX(Asynchronous Javascript And XML):异步的Javascript和XML。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(现在更多使用json数据)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应。
AJAX常见应用情景:搜索引擎根据用户输入的关键字,自动提示检索关键字;注册时候的用户名的查重,当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询用户是否存在。
优点:
AJAX使用JavaScript技术向服务器发送异步请求;
AJAX请求无须刷新整个页面;
因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
例:登陆认证页面,登陆失败不刷新页面,提示用户登陆失败,登陆成功自动跳转到网站首页。
<--login.html文件内容:--->
{% load static %} <--加载静态文件-->
...
<body>
<div>
用户名:<input type="text" id="username">
密码:<input type="text" id="pwd">
{% csrf_token %}
<button id="sub">提交</button>
<span style="color: red;font-size: 12px;" id="error"></span>
</div>
<script src="{% static 'jquery.js' %}"></script>
<script>
$('#sub').click(function () {
$.ajax({
url:"{% url 'login' %}", // url反向解析,重定向路径,避免写硬代码。注意加上引号。如果要直接写地址,如url:"/login/",第一个 / 若不写会直接和当前浏览器的地址进行拼接,如果写了会使用ID地址和端口号与之进行拼接。
type:'post', //post请求
data:{username:$('#username').val(),pwd:$('#pwd').val(),csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val()}, //为后端传入数据
success:function (data) { //data:后端返回的数据
data = JSON.parse(data);
if (data['status']){
location.href=data['home_url'];
}
else {
$('#error').text('用户名或者密码错误!')
}
}
})
})
</script>
</body>
...
<--base.html文件内容:-->
...
<body>
<h1>
欢迎
</h1>
</body>
...
# urls.py文件内容:
path('login/', views.login,name='login'),
path('home/', views.home,name='home'),
# view.py文件内容:
...
from django.http import JsonResponse
def login(request):
res_dict = {'status':None,'home_url':None}
if request.method == 'GET':
return render(request,'login.html')
else:
uname = request.POST.get('username')
pwd = request.POST.get('pwd')
user_obj = models.UserInfo.objects.filter(name=uname,password=pwd).exists()
import json
if user_obj:
res_dict['status'] = True
res_dict['home_url'] = reverse('home')
res_json_dict = json.dumps(res_dict)
return HttpResponse(res_json_dict,content_type='application/json') # 直接返回字典格式是不可以的,必须转换成json字符串,需要改变响应头中的content类型,当前端ajax拿到数据后,通过data_type或者content_type发现发送来的是个json格式的数据,那么ajax就自动将这个数据反序列化得到了js的数据对象,然后通过对象可以直接操作数据。若不改变,则还需要在前端页面反序列化。
else:
res_dict['status'] = False
return JsonResponse(res_dict) # JsonResponse自动dump数据和传递content_type类型。
def home(request):
return render(request,'base.html')
ajax里面写$(this)时要注意:如果你想在不刷新页面的情况下来添加某些dom对象,并且这个对象也需要绑定事件的话,需要用on来给和他相同的标签对象来绑定事件。
settings配置文件里面加上APPEND_SLASH=False
:即当请求用户路径的时,不自动处理路径最后面的/,如果这个值为True,假如写了一个url为path('index/',views.test)
,当用户请求127.0.0.1:8000/index
时,django会让浏览器重新再发一次请求,并且在这个路径后面加上/,即127.0.0.1:8000/index/
,此时和我们的url就能匹配上了,如果设置成false,那么用户在输入127.0.0.1:8000/index,没有最后那个斜杠的路径时,就无法和url匹配上了。但是注意,django只能重定向让浏览器再发一个get请求,当用post方法提交数据的时,就像上面ajax里那个url必须和后端配置的url对应。
Ajax的使用
基于jQuery的实现
<button class="send_Ajax">send_Ajax</button>
<script>
$(".send_Ajax").click(function(){
$.ajax({
url:"",
type:"", // POST/GET
data:{a:"a",b:"b"},
success:function(data){},
error: function (jqXHR, textStatus, err) {},
complete: function (jqXHR, textStatus) {},
statusCode: {
'403': function (jqXHR, textStatus, err) {},
'400': function (jqXHR, textStatus, err) {},
......
}
})
})
</script>
ajax参数
请求参数
data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。
processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;如果为false, 那么对data:{a:1,b:2}
会调用json对象的toString()方法,即{a:1,b:2}.toString()
,最后得到一个[object,Object]形式的结果。
contentType:默认值: "application/x-www-form-urlencoded"
。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2
;如果想以其他方式提交数据,比如contentType:"application/json"
,即向服务器发送一个json字符串:注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象。
traditional::一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]}, traditional为false会对数据进行深层次迭代。
响应参数:
dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;dataType的可用值:html|xml|json|text|script
headers:自定制请求头。
Ajax请求设置csrf_token
方式1:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
$.ajax({
data: {
"csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
}
})
方式2
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
方式3
通过获取返回的cookie中的字符串放置在请求头中发送。 注意:需要引入一个jquery.cookie.js插件。
<script src="{% static 'js/jquery.cookie.js' %}"></script>
$.ajax({
headers:{"X-CSRFToken":$.cookie('csrftoken')},
})
`content_type`:
响应头默认为:
text/html; charset=utf-8
请求头默认为:
application/x-www-form-urlencoded; charset=utf-8
即向后端的请求格式为urlencoded
,与GET请求提交数据的请求格式相同,但数据位置不同,GET请求数据放在urlhou,urlencoded
数据放在了请求体中。数据发送至后端后,Django内部调用了内置的解析器(接口的十大组件之一)将其解析。可在ajax中指定contentType类型:
$.ajax({
...
contentType:"`application/json" //指定发送json格式
data:Json.stringify({"k":"1","k2":"2"}) // data参数中的键值对,如果值不为字符串,需要将其转换成字符串类型。
success:function (data) {}
- ContentType指的是请求体的编码类型,常见的类型共有3种:
- application/x-www-form-urlencoded:浏览器的原生
- multipart/form-data:使用表单上传文件时,必须让
表单的
enctype
等于 multipart/form-data。 - application/json:用来告诉服务端消息主体是序列化后的 JSON 字符串。
- 服务端接受到数据之后,通过contenttype类型的值来使用不同的方法解析数据,django不能解析contenttype值为json的数据格式,但可以解析
application/x-www-form-urlencoded 和multipart/form-data
,如果传json类型的数据,需要自己来写一个解析数据的方法。
Django内置的serializers做序列化
源码:
def books_json(request):
book_list = models.Book.objects.all()[0:10]
from django.core import serializers
ret = serializers.serialize("json", book_list)
return HttpResponse(ret)
Json
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),但JSON 仍然独立于语言和平台,是轻量级的文本数据交换格式,具有自我描述性,更易理解。
json数据类型和python数据类型的对比:
上面的这几种数据类型进行json.dumps序列化之后都是字符串,注意是由单引号括起的,数据里面的单引号,序列化后会变成双引号。python中的datetime等时间日期类型、集合类型等是不能进行json序列化的,因为json没有对应的格式。
import json
from datetime import datetime
from datetime import date
# 对含有日期格式数据的json数据进行转换
class JsonCustomEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field,datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field,date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self,field)
d1 = datetime.now()
dd = json.dumps(d1,cls=JsonCustomEncoder)
print(dd)
不合格的json对象:
{ 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;} // 不能使用函数和日期对象
}
// JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"张三"}');
JSON.parse('{name:"张三"}') ; // 错误
JSON.parse('[18,undefined]') ; // 错误
// JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"张三"})
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。JSON 格式书写简单;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。