Ajax发送POST请求
citgpt 2024-10-24 16:20 15 浏览 0 评论
一、 Ajax 介绍
Ajax 就是可以让页不刷新的情况下,给服务器发送 HTTP 请求并获取到数据。
通过编写 JavaScript 代码,还可以把获取到的数据展示在当前页面上。
二、 jQuery 封装的 Ajax
语法格式
$.ajax({
/* url 地址可以是 /get-json/ 的方式
* 也可以是 http://www.qfedu.com/get-json/ 的方式
*/
url: 'url 地址',
type: 'GET/POST',
dataType: 'json',
success: function(res){
// 成功处理逻辑
},
error: function(res){
// 错误时处理逻辑
}
});
Django POST 方法提交表单,必须面临一个问题,那就是 CSRF_TOKEN
CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
Django 中自带了这个防止CSRF攻击的功能。
GET 请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果。
解决的思路是:
在前端代码的 form 表单内写上 {% csrf_token %},
用来接收 Django 返回的 csrf_token 的值
{% csrf_token %} 会在表单中生一个隐藏的 input 标签
<input type="hidden" name="csrfmiddlewaretoken" value="EAYZaWHO8g7ZtI4N2xPzKCvxj94sCNPnsYTCLQpQWudH38iK0vHoyYf8NtRBjcRP">
\2. 想办法把此标签的 key 和 value 作为首层数据发送到后端,Django 后端会自动获取验证
获取到 csrf_token 的 key 和 value 的方法有一下几种
从页面中的源码中获得。
当第一次请求后不论验证结果如何,前端页面在写上 {% csrf_token %}
的前提下,就会有个隐藏的 input 标签,复制他的 name 属性的值就是 key, 复制 value属性的值就是我们要的 value
从cookie 中得到。
利用 javascript.cookie.js 可以从 cookie 中得到。
javascript.cookie.js 下载地址
就在其源码的 src 目录下 。
使用方法:
// 引入
<script src="/static/jquery.cookie.js"></script>
<script>
// 获取到值
var token_val = $.cookie('csrftoken')
</script>
从 form 表单中自动获取
<form >
{% csrf_token %}
<input type="file" />
<input type="text" name="one" value="FormData_one"/>
<input type="text" name="two" value="FormData_two"/>
<button >提交</button>
</form>
<script>
$("#Ajax_FD_submit").serialize());
</script>
serialize() 会获取到在 form 标签内的所有数据,并进行序列化;这种适合提交数据比较多的情况
利用 Django 的模版语言
{{ csrf_token }} // 它就是 csrf_token 的值
注意一点: csrf_tken 的数据向后台提交的时候,必须放在首层,不要在嵌套到其他数据类中了
因为 Django 会从 GET 或 POST 的数据体内寻找固定的 csrf_token key 的值来验证。
下面来说怎么结合以上的方法,具体实现 Ajax 提交数据并进行 csrf_token 认证
第一种: 结合 JavaScript 的 FormDate 类,实现 Ajax 提交
简单介绍
实现的功能:可以提交表单中的数据和文件。
缺点:目前兼容性还不太好,因为 FormDate 这个类是比较新的特性,IE8 及一下版本的浏览器不支持。
相信随着时间的推移,这种方法会逐渐称为主流,必须掌握。
FormData
FormData 是 JavaScript 的一个新特性,他可以让你对其进行实例化出一个对象,这个对象就像是一个盒子、容器,你可以往里面填充数据,填充的方法就像是 Python 中的列表一样。目前我所知道的是每次只可以添加一对,这对儿数据就是 'key','value' 的形式。
实现
前端Ajax发送数据的代码:
<h1>Ajax上传文件</h1>
<form >
{% csrf_token %}
<input type="file" />
<input type="text" name="one" value="FormData_one"/>
<input type="text" name="two" value="FormData_two"/>
<button >Ajax提交</button>
</form>
<script>
$(function () {
$('#ajax_btn').click(function () {
var fmd_obj = new FormData(); // 实例化一个对象
// 向对象中添加数据,格式:fmd_obj.append('key','value')
fmd_obj.append('sub_file_name', document.getElementById('sub_file').files[0]);
fmd_obj.append('my_list', ['a','b']); //每次都可以向这个对象中添加一个数据
fmd_obj.append('my_key','my_value');
fmd_obj.append('csrfmiddlewaretoken','{{ csrf_token }}') // 解决认证问题
fmd_obj.append('data',$("#Ajax_FD_submit").serialize());
$.ajax({
url: "/ajax-upload/",
type: 'POST',
data: fmd_obj,
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
success:function (arg) {
console.log(arg);
},
});
return false; // 最好返回false,因为如果按钮类型是submit,或者是 button 标签,
// 则表单自己又会以 GET 的方式再提交一次;返回false阻止表单再次提交
});
});
</script>
后端接收数据的代码
def ajax_upload(request):
"""
接收前端 Ajax 发送过来的数据和文件
:param request:
:return:
"""
import os,json
response = BaseReponse()
try:
print('reqpost数据>>:', request.POST)
print('reqfile数据>>:', request.FILES)
file_obj = request.FILES.get('sub_file_name')
print('接收到的文件>>:', file_obj)
print('参数key one 的值>>:', request.POST.get('one'))
print('参数key two 的值>>:', request.POST.get('two'))
# file_dir = os.path.join(settings.BASE_DIR, 'img') # 设置接收文件的绝对路径
# print("文件保存的绝对路径>>:", file_dir)
"""下面的是把接收到的文件保存到服务器上"""
file_path = os.path.join('static', file_obj.name) # 组合文件的完整路径
new_file_obj = open(file_path, 'wb')
[new_file_obj.write(chunk) for chunk in file_obj.chunks()]
new_file_obj.close()
"""设置一下返回信息和状态"""
response.status = True
response.data = file_path
except Exception as e:
response.status = False
response.error = "上传失败"
return HttpResponse(json.dumps(response.__dict__))
后端得到的数据
reqpost数据>>: <QueryDict: {'my_list': ['a,b'], 'csrfmiddlewaretoken': ['EAYZaWHO8g7ZtI4N2xPzKCvxj94sCNPnsYTCLQpQWudH38iK0vHoyYf8NtRBjcRP'], 'my_key': ['my_value'], 'data': ['csrfmiddlewaretoken=EAYZaWHO8g7ZtI4N2xPzKCvxj94sCNPnsYTCLQpQWudH38iK0vHoyYf8NtRBjcRP&one=FormData_one&two=FormData_two']}>
reqfile数据>>: <MultiValueDict: {'sub_file': [<InMemoryUploadedFile: 乖巧中透漏这悲伤.png (image/png)>]}>
接收到的文件>>: 乖巧中透漏这悲伤.png
参数key one 的值>>: None
参数key two 的值>>: None
因为 .serialize() 得到的是 form 表单内的所有数据,所以在内层数据中也会有个 csrf_token
第二种: 利用 Form 和 ifram 实现"伪"Ajax 提交
简单介绍
实现的功能:可以提交表单和文件;目前业界比较流行
关键点
form 标签要定义一个 target 属性,其值必须与 ifram 标签的 name 属性的值相同
实现
前端"伪"Ajax发送数据的代码:
<h1>"伪"Ajax操作</h1>
//可以同时提交文件和数据
<div>
<form action="/ajax-upload/" method="POST" enctype="multipart/form-data" target="ifr">
{% csrf_token %}
<input type="file" name="sub_file_name" />
<input type="text" name="one" value="iframe_one"/>
<input type="text" name="two" value="iframe_two"/>
</form>
<iframe name="ifr"style="display: none"></iframe>
// 用于展示预览的图片
<div ></div>
</div>
<script>
// "伪"Ajax操作,自动上传
// 标签的内容有改变,就触发 change 事件
function changeImg() {
document.getElementById('ifram_form').submit(); // js 语言的提交
// $("#ifram_form").submit(); // jQuery 方法提交
}
;
// 当标签内容(包括图片和文字)加载完毕时触发 load 事件
$("#onload").load(function () {
var v = $('#onload').contents().find('body').html(); // 返回的数据会在 ifram 中,从ifram中取数据
var obj = JSON.parse(v); // JavaScript 的反序列化,把字符串转换为数据对象
alert(obj);
var tag = document.createElement('img'); // 创建一个 img 标签
tag.src = "/" + obj.data; // 给标签添加一个属性,并赋值
$('#prevImg').append(tag); // 在某一个标签的里面,添加一个这个标签的子标签
});
</script>
后端接收数据的代码
def ajax_upload(request):
"""
接收前端 Ajax 发送过来的数据和文件
:param request:
:return:
"""
import os,json
response = BaseReponse()
try:
print('reqpost数据>>:', request.POST)
print('reqfile数据>>:', request.FILES)
file_obj = request.FILES.get('sub_file_name')
print('接收到的文件>>:', file_obj)
print('参数key one 的值>>:', request.POST.get('one'))
print('参数key two 的值>>:', request.POST.get('two'))
# file_dir = os.path.join(settings.BASE_DIR, 'img') # 设置接收文件的绝对路径
# print("文件保存的绝对路径>>:", file_dir)
"""下面的是把接收到的文件保存到服务器上"""
file_path = os.path.join('static', file_obj.name) # 组合文件的完整路径
new_file_obj = open(file_path, 'wb')
[new_file_obj.write(chunk) for chunk in file_obj.chunks()]
new_file_obj.close()
"""设置一下返回信息和状态"""
response.status = True
response.data = file_path
except Exception as e:
response.status = False
response.error = "上传失败"
return HttpResponse(json.dumps(response.__dict__))
后端得到的数据
reqpost数据>>: <QueryDict: {'one': ['iframe_one'], 'csrfmiddlewaretoken': ['rASMcicdXWgDqO83szbzkVQtY5UOiKpAfYNpNcUfLaml0em0qx3o8hA4spHXZ9r2'], 'two': ['iframe_two']}>
reqfile数据>>: <MultiValueDict: {'sub_file': [<InMemoryUploadedFile: QQ截图20170305224609.png (image/png)>]}>
接收到的文件>>: QQ截图20170305224609.png
参数key one 的值>>: iframe_one
参数key two 的值>>: iframe_two
第三种: 利用 javascript.foram.js 实现 Ajax 提交
简单介绍
实现的功能:可以提交表单和文件
缺点:目前兼容性还不太好,因为 FormDate 这个类是比较新的特性,IE8 及之前版本的浏览器不支持
实现
前端Ajax发送数据的代码:
<h1>利用 Script.form.js 提交文件和表单数据</h1>
<div>
<form method="post" action="/ajax-upload/" enctype="multipart/form-data">
上传头像:
<input type="file" name="sub_file_name" />
<input type="button" value="提交" />
<input type="text" name="one" value="FormDataone"/>
<input type="text" name="two" value="FormDatatwo"/>
</form>
</div>
<script>
// script_form.js
$("#formjs_btn").on('click', function () {
var value = $("#sub_file").val()
if (!value) {
alert("请先选择文件");
return false;
}
if (!value.match(/.jpg|.jpeg|.gif|.png|.bmp/i)) {
alert("文件格式错误");
return false;
}
var inp_one = $("input[type='text']").first().val();
var inp_two = $("input[type='text']").last().val();
var option = {
url: '/ajax-upload/',
type: 'POST',
dataType: 'json',
data: {'one': inp_one, 'two': inp_two},
headers: { // 把认证信息添加到请求的头部,也能实现认证
"X-CSRFToken": $.cookie('csrftoken') // 从 cookie 中获取到csrf的值
}, // 注意这里的 key 必须是这个,这是Django 定义好的
success: function (data) {
alert(JSON.stringify(data)); // js 序列化数据,把数据对象转换为字符
},
error: function (data) {
alert("--上传失败,请刷新后重试");
}
};
$("#form0").ajaxSubmit(option); // 使用 script.form.js 上传数据和文件
return false; // 返回false阻止表单再次提交
});
</script>
后端接收数据的代码
后端接收数据的代码和第一种或者第二种一样
后端得到的数据
reqpost数据>>: <QueryDict: {'two': ['FormDatatwo', 'FormDatatwo'], 'one': ['FormDataone', 'FormDataone']}>
reqfile数据>>: <MultiValueDict: {'sub_file_name': [<InMemoryUploadedFile: 美女.jpg (image/jpeg)>]}>
接收到的文件>>: 美女.jpg
参数key one 的值>>: FormDataone
参数key two 的值>>: FormDatatwo
- 上一篇:Linux(ps -aux命令)
- 下一篇:Pandas read_csv 参数详解
相关推荐
- js中arguments详解
-
一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...
- firewall-cmd 常用命令
-
目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...
- epel-release 是什么
-
EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...
- FullGC详解 什么是 JVM 的 GC
-
前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...
-
2024-10-26 08:50 citgpt
- 跨域(CrossOrigin)
-
1.介绍 1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。 通俗讲...
- 微服务架构和分布式架构的区别
-
1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...
- 深入理解与应用CSS clip-path 属性
-
clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...
-
2024-10-25 11:51 citgpt
- Request.ServerVariables 大全
-
Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...
- python操作Kafka
-
目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...
- Runtime.getRuntime().exec详解
-
Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...
- promise.all详解 promise.all是干什么的
-
promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...
-
2024-10-24 16:21 citgpt
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracleclient (56)
- springbatch (59)
- oracle恢复数据 (56)
- 简单工厂模式 (68)
- 函数指针 (72)
- fill_parent (135)
- java配置环境变量 (140)
- linux文件系统 (56)
- 计算机操作系统教程 (60)
- 静态ip (63)
- notifyicon (55)
- 线程同步 (58)
- xcode 4 5 (60)
- 调试器 (60)
- c0000005 (63)
- html代码大全 (61)
- header utf 8 (61)
- 多线程多进程 (65)
- require_once (60)
- 百度网盘下载速度慢破解方法 (72)
- 谷歌浏览器免费入口 (72)
- npm list (64)
- 网站打开速度检测 (59)
- 网站建设流程图 (58)
- this关键字 (67)