ajax相关
1.csrf装饰器
from django.shortcuts import render, redirect, HttpResponse from django.views import View from django.conf import global_settings from django.contrib.sessions.backends import db class Login(View): def get(self, request, *args, **kwargs): return render(request, 'login.html') def post(self, request, *args, **kwargs): username = request.POST.get('username') pwd = request.POST.get('pwd') if username == 'mcw' and pwd == '123': url = request.GET.get('return_url') if url: ret = redirect(url) else: ret = redirect('/index/') # ret['Set-Cookie'] = 'is_login=100; Path=/' # ret.set_cookie('is_login', '1') # Set-Cookie: is_login=1; Path=/ # ret.set_signed_cookie('is_login', '1', 's21',max_age=10000,) # Set-Cookie: is_login=1; Path=/ # 设置设session request.session['is_login'] = 1 # request.session.set_expiry(0) return ret return render(request, 'login.html', {'error': '用户名或密码错误'}) def login_required(func): def inner(request, *args, **kwargs): # is_login = request.COOKIES.get('is_login') # is_login = request.get_signed_cookie('is_login', salt='s21', default='') is_login = request.session.get('is_login') print(is_login) url = request.path_info if is_login != 1: return redirect('/login/?return_url={}'.format(url)) # 已经登录 ret = func(request, *args, **kwargs) return ret return inner @login_required def index(request): # 获取到cookie print(request.session.session_key) request.session.clear_expired() return HttpResponse('首页') @login_required def home(request): return HttpResponse('home') def logout(request): ret = redirect('/login/') # ret.delete_cookie('is_login') # request.session.delete() # 删除session数据 不删除cookie request.session.flush() # 删除session数据 删除cookie return ret
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <form action="" method="post"> {# {% csrf_token %}#} <p> 用户名: <input type="text" name="username"> </p> <p> 密码: <input type="password" name="pwd"> </p> <p>{{ error }}</p> <button>提交</button> </form> </body> </html>
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/',views.Login.as_view()), url(r'^index/',views.index), url(r'^home/',views.home), url(r'^logout/',views.logout), ]
from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie csrf_exempt 某个视图不需要进行csrf校验 csrf_protect 某个视图需要进行csrf校验 ensure_csrf_cookie 确保生成csrf的cookie
csrf_exempt exempt意思豁免

配置文件打开csrf校验:

页面中没有使用csrf:

这样当从登陆页面post请求登陆的时候不能通过校验:这时候是开启了csrf校验但是页面没有使用csrf,也就是没有添加csrf的那个隐藏标签,就被拒绝掉了

现在是全局使用了csrf校验的。我想给某些不需要加校验,导入豁免和保护的这两个内容,并将它们以传参到登录页面的装饰器中
添加dispatch方法,将带有csrf_exempt函数名的装饰器给dispatch方法才能生效。执行父方法。加在get,post方法上当发送post请求时还是报403错误:

添加装饰器到类上,没有指定添加装饰器的是哪个方法 :

在类上面指定装饰的函数是它,指定其它的方法是报错的。校验不通过:
小结:csrf_exempt 某个视图不需要进行csrf校验

现在将settings里的csrf注释掉,所有的连接都不用添加csrf校验,正常是所有的post请求都不需要csrf验证了:

然后将csrf_protect作为参数传给方式装饰器执行,post请求又使用csrf保护起来了。

这里注释的:

这里添加了csrf

登录页面也打开了:

打印提示:

然后发送登录的post请求:没有csrf_token的cookie

导入并放在get请求上:


当发送get请求的时候确保生成csrf cookie了

现在有csrftoken,且有隐藏的csrf,这样就可以提交了

2.csrf功能
1.csrf中间件中执行process_request:
查看这个类:

私有方法以及中间件要 定义的几个方法 ;

请求之后先执行process_request这个方法,这个方法又会去执行_get_token方法

_get_token方法判断的是全局中的一个变量

默认是False:

1. 从cookie中获取到csrftoken的值

cookie的名字在请求对象中是这个,并且获取它的值:


2. csrftoken的值放入到 request.META
将cookie放进去并执行这个方法

如果你传过来的长度是这个:

长度乘积之后64,:

也就是获取到的这个值是64,然后就把他返回:


通过配置文件大小在这里判断它是64,又赋值给下面这个变量;

如果从cookie中获取的csfrtoken长度和配置计算后长度不同,就重新设置cookie,否则就返回这个cookie值

也就是下面这一步的操作是获取这个cookie值,

如果获取到了这个cookie值,那么就将它放到请求头里面,这样就能通过这个属性取请求头中cookie值;

下一步就是从请求对象中获取这个属性,csrf处理完成了就返回None。

如果上面if没走就走下面的if,拿callback,callback就是我们要执行的函数

比如登陆CBV中的post中获取csfr_exempt,豁免,不需要校验

csrf_exempt里面设置了一个属性是True

拿到这个属性值的是这里:

下面就是请求方式的判断,如果不在这些方式里就走下面的代码,否则就返回下面的_accept()

而返回的这里就是将请求对象的csrf处理完成设置成校验完成了,返回None函数结束

下面看一下进行csrf校验:
如果请求方式不在这些(post)里面那么就执行里面的代码:

如果获取到请求对象中的不设置csrf检查就返回_accept(),也就是返回一个None,csrf检查完成

https请求才会走下面:

下面就是将我们设置进请求对象中的csrf_cookie再获取出来,这个值就是我们从浏览器发给我们的csrftoken值。

这个cookie如果获取不到的话就拒绝

私有方法拒绝就是警告禁止403,获取一个失败的视图,这也就是说没有cookie的话不行,就执行这个错误显示视图函数

如果不是 空那么就是获取到csrftoken,那么将下面的设置为空字符串:

如果发送的是post请求,那么尝试在post键值对中获取csrf中间件token的值。前面给它赋值空字符串,后面将POST中取到的这个值再赋值给这个变量

即请求页面form表单中使用csrf创建的值:

当前不为空,那么下面又执行了如下方法:


这个方法还是那个64位判断的方法,它返回的还是token它本身:

然后继续往下执行,进行比较。比较加盐的这两个cookie值。成功返回true,失败返回false。也就是比较not 成功,那么拒接掉

如果比较成功那么不走下面的代码,而是返回的校验完成的私有方法

再看看如果获取的页面中的csrf中间件token是空,做的是下面的操作

获取的就是请求对象中的这个属性值

获取到之后还是和cookie的值做对比。
对比的cookie值是这个:

如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。
如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。
这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
两个对比,拿cookie和页面中 {% csrf_token %}或者请求头中的x...对比
综上:

2.执行process_view
-
查询视图函数是否使用csrf_exempt装饰器,使用了就不进行csrf的校验
-
判断请求方式:
-
如果是GET', 'HEAD', 'OPTIONS', 'TRACE'
不进行csrf校验
-
其他的请求方式(post,put)
进行csrf校验:
1.获取cookie中csrftoken的值
获取csrfmiddlewaretoken的值
能获取到 ——》 request_csrf_token
获取不到 ——》 获取请求头中X-csrftoken的值 ——》request_csrf_token
比较上述request_csrf_token和cookie中csrftoken的值,比较成功接收请求,比较不成功拒绝请求。
-
-
3.ajax
https://www.cnblogs.com/maple-shaw/articles/9524153.html
js中json序列化和反序列化:


1.发请求的方式
1.地址栏输入地址 GET
2.form表单 GET/POST
3.a标签 GET
2.ajax
就是使用js的技术发请求和接收响应的。
特点:
-
异步 #发送一个请求过去之后不用等到结果回来就可以进行发送下一个ajax请求
-
局部刷新
-
传输的数据量少
鼠标点进去:

失焦就有提示,js事件

如果 填写注册名字已经被使用,会提示出来,这是ajax和后台交互,局部刷新的效果

如下:当写入被使用了的用户名的时候会发送请求,请求url是检查名字

返回的内容是字符串:

当写入的是没有被使用的时候,返回的是True:
-
局部刷新
-
传输的数据量少

3.jqery发ajax请求
$.ajax({ url: '/calc/', type: 'post', data: { a: $("[name='i1']").val(), b: $("[name='i2']").val(), }, success: function (res) { $("[name='i3']").val(res) }, error:function (error) { console.log(error) } })
代码逻辑如下:

当你输入i1和i2点击计算的时候,后端获取到输入的id,i2,并将它们运算结果i3渲染到index.html然后返回给浏览器。


如果再来一个计算的框,那么需要再来一次(或几次)基本上是重复的代码:


下面需要很多重复的代码:

对于单一的这种情况没有必要重复性写,应该计算哪个后端发送计算结果前端进行渲染

这里不需要values了,我们需要在视图函数中接收ajax的data传递过来的数据,并将数据在函数中操作(两数之和)之后返回给ajax,然后通过js将返回来的结果渲染在页面中,实现局部刷新。


因为我们点击button的时候它会往form表单发送请求。当我们需要使用ajax传输的时候,可以不需要form表单,或者给提交按钮添加type=button。并且



这样就实现了点击计算按钮走的是ajax请求里面的url路径

这样就正常了

将httpresponse的值使用ajax将它渲染在页面中:
设置值,$('属性选择器(这就属性=‘啥’,不用加标签名字也可以的)') ,jq对象.val('值')设置jq获取的标签内容

添加内部错误:

点击计算后打印:

添加页面中点击第二个计算按钮的视图函数,前端页面修改好,让它走第二个ajax的url,而不是默认的form表单(去掉form表单或者将button按钮设置类型为button)。如下设置两个视图函数,第一个视图函数结果返回设置慢一点。


点击完1就点击2,1返回慢,所以2的先回来;这样就能看出ajax请求是异步的。

ajax参数

添加^test/路由,添加test视图函数


点击参数之后浏览器控制台成功打印服务器返回给ajax请求的httpresponse内容

但是后台传过来的是键[]作为新的字典的键了,这样的话从POST中取前端传过了的hobby键(值是有多个内容的列表)是获取不到内容的,因为名字改掉了。现在要取这些值的话需要使用字典.get('hobby[]')。

但是这里只取到最后一个,

所以应该用getlist

由于前端ajax传到后台的是字典对象,会进行url编码,会将列表做转化。我们可以直接传过去将列表格式化成字符串

这样后台拿到的有列表的键就是这个键了,而列表内容是字符串,后端可以做:


在后端我们可以自己将字符串序列化:

4.上传文件:
<input type="file" id="f1"> <button id="b1">上传</button> $('#b1').click(function () { var formobj = new FormData(); formobj.append('file',document.getElementById('f1').files[0]); // formobj.append('file',$('#f1')[0].files[0]); formobj.append('name','alex'); $.ajax({ url: '/upload/', type: 'post', data:formobj , processData:false, // contentType:false, success: function (res) { $("[name='i3']").val(res) }, }) })
写上传的视图函数,上传的页面和url



现在上传没有任何效果,我们应该用ajax传输。点击按钮事件之后发送ajax请求:button添加id,选择标签,绑定点击事件,内部执行ajax请求

创建表单数据对象
对象.append(键值对),键是名字,值是file类型的input标签的DOM对象.flies[0]
DOM对象可以直接创建文档.获得元素通过id,也可以jq获取标签然后[0]转为DOM对象。我们可以往对象里面添加其他键值对。

请求url,请求类型,data数据,就是我们创建的对象
添加processData:false,处理数据格式,默认处理的,还有contetType也是false不让它处理

选择文件上传;

文件有了,formobj中其它参数也有了:也就是当我们上传文件时,这里没用form表单,上传走的是ajax中的url,然后用new 表单数据创建这个对象,将这个对象发送给后端,视图函数中request.FILES就是文件对象,POST就是往这个对象中添加的其它键值对,并且是个字典

contenType如果true的话会当成url编码去传,文件数据是传不过去的,false的话是表单数据传


内容类型默认url编码,在这里可以查看

5.ajax通过csrf的校验:
开启csrf校验之后,ajax就有问题了

前提条件:确保有csrftoken的cookie
在页面中使用{% csrf_token %}
加装饰器 ensure_csrf_cookie
from django.views.decorators.csrf import csrf_exempt,csrf_protect, ensure_csrf_cookie
1.给data中添加csrfmiddlewaretoken的值
data: { 'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(), a: $("[name='i1']").val(), b: $("[name='i2']").val(), },
开启csrf,页面添加:

get请求页面就能返回一个csrftoken

并且页面中也有了hidden标签:

我发送ajax请求时应该将cookie也携带过去,所有ajax中要将这个input标签的键值对放到ajax的data中的对象

2.加请求头
headers:{ 'x-csrftoken':$('[name="csrfmiddlewaretoken"]').val(), },
将页面中的csrf中间件token值放到请求头这个属性中:

源码中这里写死了

请求头:

在settings中设置会覆盖全局的:这样设置,请求头属性名字在全局配置中的被它覆盖掉,用小写asd会显示在浏览器请求头上

ajax传的话是这样的:

3.使用文件
https://www.cnblogs.com/maple-shaw/articles/9524153.html
添加一个文件
从你的本地读取到cookie,根据name获取到你的值,通过js获取到请求头中的csrftoken

AJAX准备知识:JSON
什么是 JSON ?
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
啥都别多说了,上图吧!

合格的json对象:
["one", "two", "three"] { "one": 1, "two": 2, "three": 3 } {"names": ["张三", "李四"] } [ { "name": "张三"}, {"name": "李四"} ]
不合格的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;} // 不能使用函数和日期对象
}
stringify与parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"alex"}');
JSON.parse('{name:"alex"}') ; // 错误
JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"alex"})
和XML的比较
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。
JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。
XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。
用XML表示中国部分省市数据如下:
XML格式数据用JSON表示如下:
JSON格式数据由上面的两端代码可以看出,JSON 简单的语法格式和清晰的层次结构明显要比 XML 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用得带宽。
AJAX简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
示例
页面输入两个整数,通过AJAX传输到后端计算出结果并返回。
HTML部分代码
def ajax_demo1(request): return render(request, "ajax_demo1.html") def ajax_add(request): i1 = int(request.GET.get("i1")) i2 = int(request.GET.get("i2")) ret = i1 + i2 return JsonResponse(ret, safe=False)
urls.pyAJAX常见应用情景
搜索引擎根据用户输入的关键字,自动提示检索关键字。
还有一个很重要的应用场景就是注册时候的用户名的查重。
其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。
- 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
- 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。
- 整个过程中页面没有刷新,只是局部刷新了;
- 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;
AJAX的优缺点
优点:
- AJAX使用JavaScript技术向服务器发送异步请求;
- AJAX请求无须刷新整个页面;
- 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
jQuery实现的AJAX
最基本的jQuery发送AJAX请求示例:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ajax test</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> </head> <body> <button id="ajaxTest">AJAX 测试</button> <script> $("#ajaxTest").click(function () { $.ajax({ url: "/ajax_test/", type: "POST", data: {username: "Q1mi", password: 123456}, success: function (data) { alert(data) } }) }) </script> </body> </html>
views.py:
def ajax_test(request): user_name = request.POST.get("username") password = request.POST.get("password") print(user_name, password) return HttpResponse("OK")
$.ajax参数
data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
success:function (data) {
$("#i3").val(data);
}
})
})
JS实现AJAX
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var b2 = document.getElementById("b2"); b2.onclick = function () { // 原生JS var xmlHttp = new XMLHttpRequest(); xmlHttp.open("POST", "/ajax_test/", true); xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.send("username=q1mi&password=123456"); xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { alert(xmlHttp.responseText); } }; }; |
AJAX请求如何设置csrf_token
方式1
通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
$.ajax({ url: "/cookie_ajax/", type: "POST", data: { "username": "Q1mi", "password": 123456, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success: function (data) { console.log(data); } })
方式2
通过获取返回的cookie中的字符串 放置在请求头中发送。
注意:需要引入一个jquery.cookie.js插件。
$.ajax({ url: "/cookie_ajax/", type: "POST", headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 从Cookie取csrftoken,并设置到请求头中 data: {"username": "Q1mi", "password": 123456}, success: function (data) { console.log(data); } })
或者用自己写一个getCookie方法:
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');
每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。
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); } } });
注意:
如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。
如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。
这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def login(request): pass
更多细节详见:Djagno官方文档中关于CSRF的内容
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) } }) })
练习(用户名是否已被注册)
功能介绍
在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回这个用户名是否已经被注册过。
案例分析
- 页面中给出注册表单;
- 在username input标签中绑定onblur事件处理函数。
- 当input标签失去焦点后获取 username表单字段的值,向服务端发送AJAX请求;
- django的视图函数中处理该请求,获取username值,判断该用户在数据库中是否被注册,如果被注册了就返回“该用户已被注册”,否则响应“该用户名可以注册”。
序列化
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)
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")
}
}
})
});
})
AJAX准备知识:JSON
什么是 JSON ?
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
啥都别多说了,上图吧!

合格的json对象:
["one", "two", "three"] { "one": 1, "two": 2, "three": 3 } {"names": ["张三", "李四"] } [ { "name": "张三"}, {"name": "李四"} ]
不合格的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;} // 不能使用函数和日期对象
}
stringify与parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"alex"}');
JSON.parse('{name:"alex"}') ; // 错误
JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"alex"})
和XML的比较
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。
JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。
XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。
用XML表示中国部分省市数据如下:
XML格式数据用JSON表示如下:
JSON格式数据由上面的两端代码可以看出,JSON 简单的语法格式和清晰的层次结构明显要比 XML 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用得带宽。
AJAX简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
示例
页面输入两个整数,通过AJAX传输到后端计算出结果并返回。
HTML部分代码
def ajax_demo1(request): return render(request, "ajax_demo1.html") def ajax_add(request): i1 = int(request.GET.get("i1")) i2 = int(request.GET.get("i2")) ret = i1 + i2 return JsonResponse(ret, safe=False)
urls.pyAJAX常见应用情景
搜索引擎根据用户输入的关键字,自动提示检索关键字。
还有一个很重要的应用场景就是注册时候的用户名的查重。
其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。
- 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
- 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。
- 整个过程中页面没有刷新,只是局部刷新了;
- 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;
AJAX的优缺点
优点:
- AJAX使用JavaScript技术向服务器发送异步请求;
- AJAX请求无须刷新整个页面;
- 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
jQuery实现的AJAX
最基本的jQuery发送AJAX请求示例:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ajax test</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> </head> <body> <button id="ajaxTest">AJAX 测试</button> <script> $("#ajaxTest").click(function () { $.ajax({ url: "/ajax_test/", type: "POST", data: {username: "Q1mi", password: 123456}, success: function (data) { alert(data) } }) }) </script> </body> </html>
views.py:
def ajax_test(request): user_name = request.POST.get("username") password = request.POST.get("password") print(user_name, password) return HttpResponse("OK")
$.ajax参数
data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
success:function (data) {
$("#i3").val(data);
}
})
})
JS实现AJAX
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var b2 = document.getElementById("b2"); b2.onclick = function () { // 原生JS var xmlHttp = new XMLHttpRequest(); xmlHttp.open("POST", "/ajax_test/", true); xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.send("username=q1mi&password=123456"); xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { alert(xmlHttp.responseText); } }; }; |
AJAX请求如何设置csrf_token
方式1
通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
$.ajax({ url: "/cookie_ajax/", type: "POST", data: { "username": "Q1mi", "password": 123456, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success: function (data) { console.log(data); } })
方式2
通过获取返回的cookie中的字符串 放置在请求头中发送。
注意:需要引入一个jquery.cookie.js插件。
$.ajax({ url: "/cookie_ajax/", type: "POST", headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 从Cookie取csrftoken,并设置到请求头中 data: {"username": "Q1mi", "password": 123456}, success: function (data) { console.log(data); } })
或者用自己写一个getCookie方法:
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');
每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。
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); } } });
注意:
如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。
如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。
这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def login(request): pass
更多细节详见:Djagno官方文档中关于CSRF的内容
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) } }) })
练习(用户名是否已被注册)
功能介绍
在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回这个用户名是否已经被注册过。
案例分析
- 页面中给出注册表单;
- 在username input标签中绑定onblur事件处理函数。
- 当input标签失去焦点后获取 username表单字段的值,向服务端发送AJAX请求;
- django的视图函数中处理该请求,获取username值,判断该用户在数据库中是否被注册,如果被注册了就返回“该用户已被注册”,否则响应“该用户名可以注册”。
序列化
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)
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")
}
}
})
});
})


浙公网安备 33010602011771号