django -- AJAX
前戏
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
看个小栗子,页面输入两个整数,通过ajax返回后台,经过后台计算返回到页面
html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="text" name="t1">+ <input type="text" name="t2">= <input type="text" name="t3">= <button id="b1">结果</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/test/', type:'post', data:{ t1:$('[name="t1"]').val(), t2:$('[name="t2"]').val() }, success:function (res) { $('[name="t3"]').val(res) } }) }) </script> </body> </html>
路由:
url(r'^calc/', views.calc), url(r'^test/', views.test),
视图
def calc(request): return render(request, 'test.html') def test(request): print(request.POST.get('t1'), request.POST.get('t2')) i1 = int(request.POST.get('t1')) i2 = int(request.POST.get('t2')) i3 = i1 + i2 return HttpResponse(i3)
这样我们在页面输入两个整数,点击“结果”按钮就通过ajax发送到后台了,然后后台计算,在返回到页面
AJAX的参数
url: '/calc/', # url地址 type: 'post', # 请求方式 data: { # 发送的数据 i1: $('[name="i1"]').val(), i2: $('[name="i2"]').val() hobby:JSON.stringify(['运维','开发','测试']) # 传个列表 进行序列化 }, success: function (res) { # 回调函数 成功时调用 res 返回的内容 console.log(res); $('[name="i3"]').val(res) }
AJAX处理csrf_token
上面的例子,我们都是把csrf注释掉了,在实际的项目中肯定不能这么干,那还有其他的方法吗?
方法一:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。只需要改htm<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% csrf_token %} <input type="text" name="t1">+ <input type="text" name="t2">= <input type="text" name="t3">= <button id="b1">结果</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/test/', type:'post',
data:{ t1:$('[name="t1"]').val(), t2:$('[name="t2"]').val(), "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success:function (res) { $('[name="t3"]').val(res) } }) }) </script> </body> </html>
方法二:通过获取返回的cookie中的字符串 放置在请求头中发送。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% csrf_token %} <input type="text" name="t1">+ <input type="text" name="t2">= <input type="text" name="t3">= <button id="b1">结果</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/test/', type:'post', headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()}, // 从Cookie取csrftoken,并设置到请求头中 data:{ t1:$('[name="t1"]').val(), t2:$('[name="t2"]').val() }, success:function (res) { $('[name="t3"]').val(res) } }) }) </script> </body> </html>
方法三:上面我们是给一个ajax设置,如果有多个,就要一一进行设置,我们可以统一进行设置
我们需要有个js文件,首先去settings.py里设置静态文件
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]
在static文件夹下创建一个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); } } });
最后再html文件里引入js文件就可以了
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="text" name="t1">+ <input type="text" name="t2">= <input type="text" name="t3">= <button id="b1">结果</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script src="/static/ajax_setting.js"></script> <script> $('#b1').click(function () { $.ajax({ url:'/test/', type:'post', data:{ t1:$('[name="t1"]').val(), t2:$('[name="t2"]').val() }, success:function (res) { $('[name="t3"]').val(res) } }) }) </script> </body> </html>
说明:使用第三种全局的设置,需要确保cookies中存在csrftoken值
如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。
这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def test(request): print(request.POST.get('t1'), request.POST.get('t2')) i1 = int(request.POST.get('t1')) i2 = int(request.POST.get('t2')) i3 = i1 + i2 return HttpResponse(i3)
AJAX上传文件
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% csrf_token %} <input type="file" id="my_file"> <button id="b1">上传</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script src="/static/ajax_setting.js"></script> <script> $('#b1').click(function () { var form_obj = new FormData(); form_obj.append('f1',$('#my_file')[0].files[0]); $.ajax({ url : '/upload/', type : 'post', data : form_obj, processData : false, // 告诉jQuery不要去处理发送的数据 contentType : false, // 告诉jQuery不要去设置Content-Type请求头 success:function (res) { console.log(res) } } ) }) </script> </body> </html>
视图函数
def upload(request): if request.is_ajax(): # 判断是不是ajax请求 f1 = request.FILES.get('f1') with open(f1.name, 'wb') as f: for i in f1.chunks(): f.write(i) return HttpResponse('上传成功') return render(request,'upload.html')