AJAX简介

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”. 即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据).

AJAX的特点:

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

这里穿插异步同步的概念:

同步: 线程提交任务后, 必须原地等待任务结果产生, 才能继续执行下一行代码
异步: 线程提交任务后, 无需等待结果的产生, 直接执行下一行代码. 当结果产生后, 会触发回调函数来处理结果.

局部刷新: 使用ajax与服务器进行数据交换后, 会通过js代码进行dom操作进行局部的页面替换, 不会刷新整个页面. 因此ajax的性能也比较高.

JS实现AJAX

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% csrf_token %}
<button id="id_js_button">原生js发送ajax请求</button>
</body>
<script>
var b2 = document.getElementById("id_js_button");
b2.onclick = function () {
// 原生JS
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("post", "/test_ajax/", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var csrf_token = document.getElementsByTagName('input')[0].value;
console.log(csrf_token);
xmlHttp.send("username=test&password=123456&csrfmiddlewaretoken=" + csrf_token);
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
alert(xmlHttp.responseText);
}
};
};
</script>
</html>

由于原生js发送ajax请求步骤太过麻烦与复杂, 下面发送的ajax请求都是基于jQuery发送的.

JQuery实现AJAX

基本的实现流程:

contentType: urlencoded

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
{% csrf_token %}
<button id="id_jQuery_button">jQuery发送ajax请求</button>
</body>
<script>
$('#id_jQuery_button').click(function () {
$.ajax({
// url后面的参数表示需要提交的地址, 不写默认给当前地址提交
url: '',
// type表示提交的方式, get, post, application/json
type: 'post',
// data后面的参数是表示需要上传的数据
data: {
'username': 'root', 'password': '123', 'csrfmiddlewaretoken': '{{csrf_token}}',
},
// success表示服务端给出响应后执行的回调函数
// 数据传递给data接收
success: function (data) {
console.log(data);
}
})
})
</script>
</html

上面虽然是基于ajax发送post请求的, 但是它的默认编码方式还是urlencoded, 可以从浏览器的请求中看出

下面将利用json来进行数据的交互

contentType: application/json

<script>
$('#id_jQuery_button').click(function () {
var send_data = {
'username': 'root',
'password': '123',
}; $.ajax({
// url后面的参数表示需要提交的地址, 不写默认给当前地址提交
url: '',
// type表示提交的方式, get, post, application/json
type: 'post',
// 发送post请求, 需要注意这里必须携带上这个参数, 否则会403错误
headers: {
'X-CSRFTOKEN': '{{csrf_token}}'
},
//发送json数据格式的话, 需要改变contentType参数
contentType: 'application/json',
// data后面的参数是表示需要上传的数据
data: JSON.stringify(send_data),
// success表示服务端给出响应后执行的回调函数
// 数据传递给data接收
success: function (data) {
console.log(data);
}
})
})
</script>

使用json传输数据需要注意的是, 后端处理的过程也有点不一样了. Django不会处理json数据, 而是把数据放在body里面让我们自己来处理.

def test_ajax(request):
if request.is_ajax():
# 发送过来的如果是json字符串, Django不会帮我们来处理
# 会将数据保存在body中, 需要我们自己处理
print(request.body)
import json
print(json.loads(request.body, encoding='utf-8'))
return JsonResponse({'code': 100, 'msg': '收到'}) return render(request, 'ajax_test.html') # out:
# b'{"username":"root","password":"123"}'
# {'username': 'root', 'password': '123'}

最后补充个json和Python数据类型相互转换的结果.

+---------------+-------------------+
| JSON | Python |
+===============+===================+
| object | dict |
+---------------+-------------------+
| array | list |
+---------------+-------------------+
| string | str |
+---------------+-------------------+
| number (int) | int |
+---------------+-------------------+
| number (real) | float |
+---------------+-------------------+
| true | True |
+---------------+-------------------+
| false | False |
+---------------+-------------------+
| null | None |
+---------------+-------------------+

contentType: multipart/form-data;

最后一种是利用ajax发送了form-data格式的数据.

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-offset-2 col-md-8">
<h2>ajax上传文件</h2>
<hr>
<form>
{% csrf_token %}
<div class="form-group">
<label for="InputFile">选择图片</label>
<span>
<label for="InputFile">
<img src="" alt="" width="200px" id="displayImg">
</label>
<input type="file" id="InputFile" style="display: none">
</span>
</div>
<button type="button" class="btn btn-default" id="submit">提交</button>
</form>
</div>
</div>
</div>
</body>
<script>
// 把选择的图片渲染到上面.
let imgReader = new FileReader();
$('#InputFile').change(function () {
// 从选择的文件读取内容
let selectFile = $('#InputFile')[0].files[0];
imgReader.readAsDataURL(selectFile);
// 等待读取完全
imgReader.onload = function () {
// 将图片渲染到展示框
$('#displayImg').attr('src', imgReader.result);
};
}); $('#submit').on('click', function () {
// 这里获取文件内容并上传
let formData = new FormData();
let selectFile = $('#InputFile')[0].files[0];
formData.append('file', selectFile);
formData.append('csrfmiddlewaretoken', '{{ csrf_token }}');
$.ajax({
url: '',
type: "post",
data: formData,
// ajax上传文件一定要指定这两个参数
contentType: false,
processData: false,
success: function (data) {
if (data.code === 100) {
alert('文件上传成功!');
} else {
alert('上传失败!')
}
}
})
})
</script>
</html>

view.py

def upload(request):
if request.method == 'POST' and request.is_ajax():
# 获取文件信息
print(request.FILES)
# 读取文件保存到本地中
file = request.FILES.get('file')
with open(file.name, 'wb') as f:
for chunk in file.chunks():
f.write(chunk)
return JsonResponse({'code': 100})
return render(request, 'upload.html', locals())

上传文件使用FormData传输, Content-Type自动指定为form-data.

传输csrf_token的其他方式

上面几个例子, 都看出来了每次遇到post请求, 都需要我们手动传csrf_token参数, 这样非常麻烦, 因此我们可以更改jQuery的ajax传递方式, 在传输数据之前, 加入我们需要的csrf_token就可以了. 详细的信息参考Django官方文档

方式1: 从cookie中获取

注意:需要引入一个jquery.cookie.js插件。

<script>
$.ajax({
url: "/cookie_ajax/",
type: "POST",
headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 从Cookie取csrf_token,并设置ajax请求头
data: {"username": "test", "password": 123456},
success: function (data) {
console.log(data);
}
})
</script>

方式2: 自己写一个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');

方式3: 直接使用$.ajaxSetup()方法为ajax请求统一设置, 即在发送前设置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);
}
}
});

注意: 上面这几种方式都是基于jQuery上解决的, 需要先引入jQuery文件, 才能生效.

小练习

写一个注册页面, 能够让用户将光标移开后能够显示用户名是否已被注册过, 将光标重新聚焦输入, 又会将错误信息清空.

注册页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body> <div class="container">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<h2>注册页面</h2>
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名</label>
<input type="text" class="form-control" name="username" id="id_username">
<span class="pull-right"></span>
</div>
<div class="form-group">
<label for="id_password">密码</label>
<input type="text" class="form-control" name="password" id="id_password">
<span class="pull-right"></span>
</div>
<div class="form-group">
<input type="button" class="btn btn-success" id="id_submit" value="提交">
</div>
</div>
</div>
</div>
<script>
$('#id_username').blur(function () {
// 判断当用户用户名框移出, 就向服务器发送请求
let username = $(this).val();
let $username = $(this);
$.ajax({
url: '',
type: 'post',
data: {'username': username, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
success: function (data) {
if (data.code === 100){
$username.next().css('color', 'black').text('用户名可以使用').parent().addClass('has-success');
} else if (data.code === 101) {
$username.next().text('用户名不能为空').css('color', 'red').parent().addClass('has-error');
} else{
$username.next().text('用户名已存在').css('color', 'red').parent().addClass('has-error')
}
}
})
}).focus(function () {
$(this).next().text('').parent().removeClass('has-error');
});
</script>
</body>
</html>

views.py

def reg(request):
if request.method == 'POST':
username = request.POST.get('username')
back_dic = {'code': 100, 'msg': ''}
if username in ['a', 'b', 'c']:
back_dic['code'] = 102
back_dic['msg'] = '用户名已存在'
elif not username:
back_dic['code'] = 101
back_dic['msg'] = '用户名不能为空'
else:
back_dic['msg'] = '用户名可以使用'
return JsonResponse(back_dic)
return render(request, 'reg.html')

django-ajax传输数据的更多相关文章

  1. Django Ajax的使用

    简介: AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. AJAX ...

  2. Django ajax的简单使用、自定义分页器

    一. ajax初识 1. 前后端传输数据编码格式contentType 使用form表单向后端提交数据时,必须将form表单的method由默认的get改为post,如果提交的数据中包含文件,还要将f ...

  3. Django ajax MYSQL Highcharts<1>

    Another small project with django/Ajax/Mysql/Highcharts. 看下效果图  - delivery dashboard .嘿嘿 是不是还蛮好看的. 废 ...

  4. django ajax练习

    这几天遇到了django ajax请求出错的问题,总结一下 前端js:我这里创建的是一个字典格式的数据,前端js收到字典之后也是要用字典的形式去解包后台传送过来的数据,比如我下面的写法:data['s ...

  5. 关于Django Ajax CSRF 认证

    CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的 ...

  6. django ajax增 删 改 查

    具于django ajax实现增 删 改 查功能 代码示例: 代码: urls.py from django.conf.urls import url from django.contrib impo ...

  7. python学习-- Django Ajax CSRF 认证

    使用 jQuery 的 ajax 或者 post 之前 加入这个 js 代码:http://www.ziqiangxuetang.com/media/django/csrf.js /*======== ...

  8. Django之Ajax传输数据

    MTV与MVC模型 MTV与MVC都是模型,只不过MTV是django自己定义的,具体看一下他们的意思 MTV模型(django) M:模型层(models.py) T:templates文件夹 V: ...

  9. Django 学习笔记(五) --- Ajax 传输数据

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  10. django使用ajax传输数据

    HTML文件ajax get例子 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

随机推荐

  1. vue 首次加载缓慢/刷新后加载缓慢 原因及解决方案

    # vue 首次加载缓慢/刷新后加载缓慢 原因及解决方案 最近做项目发现一个问题,页面每次刷新后加载速度都非常慢,20s左右,在开发环境则非常流畅,几乎感觉不到,本文参考望山的各种方案优化 1,关闭打 ...

  2. 【原创】go语言学习(十一)package简介

    目录 Go源码组织方式 main函数和main包 编译命令 自定义包 init函数以及执行行顺序 _标识符 Go源码组织方式 1. Go通过package的方式来组织源码 package 包名 注意: ...

  3. Phpstudy隐藏后门

    Phpstudy隐藏后门 1.事件背景 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOptimizer多款 ...

  4. Vim任意代码执行漏洞(CVE-2019-12735)

    Vim通过Modelines执行任意代码 漏洞概要: 在8.1.1365之前的Vim和在0.3.6之前的Neovim很容易通过打开特制的文本文件而通过模型执行任意代码. 复现条件: 确保未禁用mode ...

  5. Web for pentester_writeup之File Include篇

    Web for pentester_writeup之File Include篇 File Include(文件包涵) Example 1 加一个单引号 从报错中我们可以获取如下信息: 当前文件执行的代 ...

  6. K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法

    1. 基于实例的学习算法 0x1:数据挖掘的一些相关知识脉络 本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科. 其实人类的科学技术发展的历史,就一直伴随 ...

  7. js动态显示当前时间+数字大小转换+小于9前面补0

    <script type="text/javascript"> function getTime(){ var myDate = new Date(); // 年份 d ...

  8. 问题 L: 「Usaco2005 Feb」竞选划区O(∩_∩)O 纯属的暴力

    题目描述 农场被划分为5x5的格子,每个格子中都有一头奶牛,并且只有荷斯坦(标记为H)和杰尔西(标记为J)两个品种. 如果一头奶牛在另一头上下左右四个格子中的任一格里,我们说它们相连. 奶牛要大选了. ...

  9. Subline Text3最新激活方法解决 That license key doesn't appear to be valid.

    第一步: 管理员身份登录系统 第二步: 进入到 C:\Windows\System32\drivers\etc (这个路径可以复制,都是一样的) 第三步: 右键hosts这个文件(打开方式 - 选择记 ...

  10. Python文件打包exe教程——Pyinstaller(亲测有效)

    今天将要解决一个问题,如何打包Pyhon文件 众所周知,Python文件的后缀名为“.py” 所以执行Python文件的要求之一便是具有python环境. 偶尔特殊情况,或者运行一些比较简单的工具,但 ...