Ajax的原理及Django上传组件
title: Ajax的原理及Django上传组件
tags: Django
Ajax的原理及Django上传组件
Ajax的原理
ajax 是异步JavaScript和xml
ajax就是向后台提交数据但是不刷新页面
原生Ajax XMLHttprequest
- 创建一个XMLHttprequest对象
- 回调函数onreadystatechange 对应jQuery中的success
- 状态值是不断变化的,4代表完成,已经接收到全部响应数据;
- open是创建请求
- send是发送数据
XMLHttprequest对象的主要方法:
a. void open(String method,String url,Boolen async)
用于创建请求
参数:
method: 请求方式(字符串类型),如:POST、GET、DELETE...
url: 要请求的地址(字符串类型)
async: 是否异步(布尔类型)
b. void send(String body)
用于发送请求
参数:
body: 要发送的数据(字符串类型)
c. void setRequestHeader(String header,String value)
用于设置请求头
参数:
header: 请求头的key(字符串类型)
vlaue: 请求头的value(字符串类型)
d. String getAllResponseHeaders()
获取所有响应头
返回值:
响应头数据(字符串类型)
e. String getResponseHeader(String header)
获取响应头中指定header的值
参数:
header: 响应头的key(字符串类型)
返回值:
响应头中指定的header对应的值
f. void abort()
终止请求
XMLHttprequest的主要属性
a. Number readyState
状态值(整数)
详细:
0-未初始化,尚未调用open()方法;
1-启动,调用了open()方法,未调用send()方法;
2-发送,已经调用了send()方法,未接收到响应;
3-接收,已经接收到部分响应数据;
4-完成,已经接收到全部响应数据;
b. Function onreadystatechange
当readyState的值改变时自动触发执行其对应的函数(回调函数)
c. String responseText
服务器返回的数据(字符串类型)
d. XmlDocument responseXML
服务器返回的数据(Xml对象)
e. Number states
状态码(整数),如:200、404...
f. String statesText
状态文本(字符串),如:OK、NotFound..
GET 请求
下面是通过GTE在URL中发用的数据
<input type="button" id="btn2" value="原生 Ajax" onclick="add2();">
<script>
function add2() {
var xhr = new XMLHttpRequest(); //创建一个XMLHttpRequest对象
xhr.onreadystatechange = function () {
//回调函数 状态值是4的时候代表数据返回成功
if(xhr.readyState==4){
alert(xhr.responseText); // 服务器返回的数据
}
};
xhr.open('GET','/add2/?i1=1&i2=3'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.send();
}
</script>
def add2(request):
if request.method == "GET":
i1 =int(request.GET.get('i1'))
i2 =int(request.GET.get('i2'))
print('add2')
return HttpResponse(i1+i2)
POST请求
POST请求的内容需要放到请求体中发送,而且需要设置请求头
1 没有设置请求头的情况
<script>
function add2() {
var xhr = new XMLHttpRequest(); //创建一个XMLHttpRequest对象
xhr.onreadystatechange = function () {
//回调函数 状态码是4的时候代表数据返回成功
if(xhr.readyState==4){
alert(xhr.responseText); // 服务器返回的数据
}
};
xhr.open('POST','/add2/'); // 第一个参数是method 第二个是URL 第三个是默认异步(不用写)
xhr.send('i1=1&i2=3'); //发送的内容放到请求体中
}
</script>
在后台从request.POST中获取不到数据,数据存在request.body中
def add2(request):
if request.method == "GET":
i1 =int(request.GET.get('i1'))
i2 =int(request.GET.get('i2'))
print('add2')
return HttpResponse(i1+i2)
else:
print(request.POST)
print(request.body)
return HttpResponse("...")
结果:
<QueryDict: {}> post中没有数据
b'i1=1&i2=3' body总的数据
2 设置请求头
- xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
var xhr = new XMLHttpRequest(); //创建一个XMLHttpRequest对象
xhr.onreadystatechange = function () {
//回调函数 状态码是4的时候代表数据返回成功
if(xhr.readyState==4){
alert(xhr.responseText); // 服务器返回的数据
}
};
xhr.open('POST','/add2/'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); //添加请求头
xhr.send('i1=1&i2=3');
jQueryAjax
jQuery本身是没有ajax的,是封装了原生的ajax
使用jQuery的ajax的计算器
<input type="text" id="i1">
+
<input type="text" id="i2">
=
<input type="text" id="i3">
<input type="button" id="btn1" value="jQuery Ajax" onclick="add1();">
<script src="/static/jquery-1.12.4.js"></script>
<script>
function add1() {
$.ajax({
url:'/add1/',
type:'POST',
data:{
'i1':$('#i1').val(),
'i2':$('#i2').val(),
},
success:function (arg) {
$('#i3').val(arg)
}
})
}
</script>
def add1(request):
a1 = int(request.POST.get('i1'))
a2 = int(request.POST.get('i2'))
return HttpResponse(a1+a2)
伪Ajax,非XMLHttprequest
iframe标签具有不刷新打开页面的功能
结合Form发送,form设置成通过iframe进行发送数据。
关键点是target
1 iframe的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<input type="text" id="tex1">
<input type="button" value="查看" onclick="changeScr();">
</div>
<iframe id="ifr" style="width: 1000px;height: 2000px" src="https://www.baidu.com"></iframe>
<script>
function changeScr() {
var inp = document.getElementById('tex1').value; //value 获取文本中的内容
document.getElementById('ifr').src=inp; // 找到iframe标签并设置src属性
}
</script>
</body>
</html>
2 iframe结合form
target是iframe 的name属性的名字,这样form就会通过iframe进行发送
<form action="/fake_ajax/" method="POST" id="f1" target="ifrname">
<iframe name="ifrname" id="ifr" ></iframe>
<input type="text" name="user">
<input type="submit">
</form>
3 伪ajax的回调函数
使用onload,在iframe加载完后就代表数据发送回来了
- 把iframe的样式隐藏display none
- 使用js提交表单,否则onload会是未定义
<form action="/fake_ajax/" method="POST" id="f1" target="ifrname">
<iframe name="ifrname" id="ifr" style="display: none"></iframe>
<input type="text" name="user">
<a onclick="submitForm();">提交</a>
</form>
<script>
function submitForm() {
document.getElementById('ifr').onload = loadIframe; // 绑定事件后执行函数
document.getElementById('f1').submit(); //js提交表单
}
//回调函数
function loadIframe() {
alert(123);
{# var content = document.getElementById('ifr').contentWindow.document.body.innerText;#}
{# alert(content);#}
}
</script>
4 获取iframe中的内容
iframe 实际是在当前页面嵌套了一个页面,存放在body中。
要进入,就要获取这个对象。用contentWindow,进入iframe的对象
<script>
function submitForm() {
document.getElementById('ifr').onload = loadIframe; // 绑定事件后执行函数
document.getElementById('f1').submit(); //js提交表单
}
//回调函数
function loadIframe() {
var content = document.getElementById('ifr').contentWindow.document.body.innerText;
alert(content);//
}
</script>
Ajax上传文件
上面通过XMLHttpresquest发送的是字符串,下面发送的是文件,具体说是文件对象,包含发送的文件的信息。
XMLHttpresquest
利用XMLHttpresquest发送数据,还需要一个formData对象,
用 formData.append('k1','v1');
添加发送的数据
原生
1 用formdata发送字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>原生ajax上传文件</h1>
<a onclick="upload1();">上传</a>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload1() {
var formData = new FormData(); //用一个FormData对象发送
formData.append('k1','v1');
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState==4){
alert(xhr.responseText)
}
};
xhr.open('POST','/upload/'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); //添加请求头
xhr.send(formData); //发送formData对象
};
</script>
</body>
</html>
后台获取的数据:
def upload(request):
if request.method == "GET":
return render(request, 'upload.html')
else:
print(request.POST) # 查看POST获取的信息
return HttpResponse('...')
结果:
<QueryDict: {'------WebKitFormBoundaryyPbfiKT1zk4kFYTP\r\nContent-Disposition: form-data': [''], ' name': ['"k1"\r\n\r\nv1\r\n------WebKitFormBoundaryyPbfiKT1zk4kFYTP--\r\n']}>
1.1 formdata对象发送字符串
上面的情况是加上了请求头,这是自己用原生的XMLHttpresponse发送数据的时候
而formdata能够自动处理发送的数据(字符串、文件)
formdata发送字符串在后台直接获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>原生ajax上传文件</h1>
<a onclick="upload1();">上传</a>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload1() {
var formData = new FormData(); //用一个FormData对象发送
formData.append('k1','v1');
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState==4){
alert(xhr.responseText)
}
};
xhr.open('POST','/upload/'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.send(formData); //发送formData对象
};
</script>
</body>
</html>
后台获取的数据:
<QueryDict: {'k1': ['v1']}>
2 formdata对象发送文件
- 创建FormData对象
- 添加要发送的文件对象的,是一个列表,包含文件的信息
document.getElementById('i1').files[0]
- send(formdata) 最后发送的是formdata对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>原生ajax上传文件</h1>
<input type="file" id="i1">
<a onclick="upload1();">上传</a>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload1() {
var formData = new FormData(); //用一个FormData对象发送
formData.append('k1','v1');
formData.append('upload_file',document.getElementById('i1').files[0]); // 把文件对象的列表放到这里
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState==4){
var file_path = xhr.responseText;
alert(file_path)
}
};
xhr.open('POST','/upload/'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.send(formData); //发送formData对象
}
</script>
</body>
</html>
后台
- 获取文件对象file_obj,
request.FILES.get('upload_file')
,文件名和前端对应 - 这个文件对象打印出来的是文件的名字
- 文件对象中chunks()是存在内存中的。保存文件要从内存保存到本地
- 拼接文件路径
- 把文件的路径返回到前端
def upload(request):
if request.method == "GET":
return render(request, 'upload.html')
else:
print(request.POST)
print(request.FILES)
file_obj = request.FILES.get('upload_file') # 获取上传文件的对象,获取的是formdata对象的第一个参数名
print(file_obj) # file_obj 是文件本身 打印出来的是文件的名字
print("...")
print(file_obj.chunks()) # 这个是内存中的 <generator object InMemoryUploadedFile.chunks at 0x000000000461EF10>
file_path = os.path.join('static', file_obj.name) # 拼接路径 然后保存
print(file_path)
with open(file_path, 'wb') as f:
"""
打开文件
模式:wb 写入
一点点打开文件并写入
"""
for chunk in file_obj.chunks(): # 这里是chunks() 写错了chunks
f.write(chunk)
return HttpResponse(file_path) # 把文件的路径返回到前端
3 ajax上传图片并预览
- 返回上传文件的路径
- 路径加 / + file_path 进行拼接
- 动态创建img 添加src
- 找到div appendchild
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>原生ajax上传文件</h1>
<input type="file" id="i1">
<a onclick="upload1();">上传</a>
<div id="container1">
</div>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload1() {
var formData = new FormData(); //用一个FormData对象发送
formData.append('k1','v1');
formData.append('upload_file',document.getElementById('i1').files[0]); // 把文件对象的列表放到这里
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState==4){
var file_path = xhr.responseText;
alert(file_path);
var tag = document.createElement('img'); // 动态创建img标签
tag.src ='/'+ file_path; // 静态文件路径的开头有 斜杠
document.getElementById('container1').appendChild(tag); // 把img 添加到container1
}
};
xhr.open('POST','/upload/'); // 第一个参数是method 第二个是URL 第三个是默认异步
xhr.send(formData); //发送formData对象
}
</script>
</body>
</html>
使用jQuery
jQuery内部也是用的XMLHttpresquest,也是用formdata,还需要告知jQuery不在请求头添加内容
contentType:false,processData:false,
否则遇到的错误是:Uncaught TypeError: Illegal invocation
DOM 对象和jQuery对象的转换
jQuery -> DOM :$('#i2')[0] # 取0就是第一个元素
DOM -> jQuery : $(document.getElementById('i2')) #直接加$
http://www.cnblogs.com/Python666/p/6925517.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>jQuery ajax上传文件</h1>
<input type="file" id="i2">
<a onclick="upload2();">上传</a>
<div id="container2"></div>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload2() {
var formData = new FormData(); //用一个FormData对象发送
formData.append('k1','v1');
{# formData.append('upload_file',document.getElementById('i2').files[0]);#}
formData.append('upload_file',$('#i2')[0].files[0]); // 使用jQuery获取文件对象
/*
DOM 对象和jQuery对象的转换
DOM -> jQuery :$('#i2')[0]
jQuery -> DOM : $(document.getElementById('i2'))
*/
$.ajax({
url:'/upload/',
type:'POST',
data:formData,
contentType:false,
processData:false,
success:function (arg) {
alert(arg);
var tag = document.createElement('img'); // 动态创建img标签
tag.src ='/'+ arg; // 返回值args就是文件路径 静态文件路径的开头有 斜杠
{#document.getElementById('container2').appendChild(tag); // 把img 添加到container1#}
$('#container2').append(tag); //使用js动态添加
}
})
}
</script>
</body>
</html>
伪Ajax
伪Ajax上传的兼容性好,form上传的参数enctype="multipart/form-data"
- 设置input标签的name为upload_file,后台获取name属性名-> 获取文件对象
- XMLHttprequest 是通过formData append中 与后台的获取文件对象的名字一致
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>伪ajax上传文件</h1>
<form id="f1" method="POST" action="/upload/" target="ifr" enctype="multipart/form-data">
<iframe id="ifr" name="ifr" style="display: none;"></iframe>
<input type="file" name="upload_file"> {# 后台获取name 获取文件对象 #}
<a onclick="upload3()">伪ajax上传</a>
</form>
<div id="container3"></div>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function upload3() {
document.getElementById('ifr').onload = loadFrame;
document.getElementById('f1').submit();//form通过js进行提交
}
function loadFrame() {
var content = document.getElementById('ifr').contentWindow.document.body.innerText;
{#alert(content);// 返回的是文件的路径#}
var tag = document.createElement('img');
tag.src = '/' + content;
$('#container3').append(tag);
}
</script>
</body>
</html>
好看的上传按钮,通常是把原来的input加上了透明度opacity=0
,设置zindex
,
在下面的一层加上好看的按钮 zindex的值小于input的
参考:
http://www.cnblogs.com/wupeiqi/articles/5703697.html
Ajax的原理及Django上传组件的更多相关文章
- Django学习——ajax发送其他请求、上传文件(ajax和form两种方式)、ajax上传json格式、 Django内置序列化(了解)、分页器的使用
1 ajax发送其他请求 1 写在form表单 submit和button会触发提交 <form action=""> </form> 注释 2 使用inp ...
- ajax上传组件
BJUI框架的异步上传组件功能. 初始化: 1.Data属性:div添加属性data-toggle="upload"后可触发上传组件. 示例代码: <div class=&q ...
- Fine Uploader文件上传组件
最近在处理后台数据时需要实现文件上传.考虑到对浏览器适配上采用Fine Uploader. Fine Uploader 采用ajax方式实现对文件上传.同时在浏览器中直接支持文件拖拽[对浏览器版本有要 ...
- ajax方式提交带文件上传的表单,上传后不跳转
ajax方式提交带文件上传的表单 一般的表单都是通过ajax方式提交,所以碰到带文件上传的表单就比较麻烦.基本原理就是在页面增加一个隐藏iframe,然后通过ajax提交除文件之外的表单数据,在表单数 ...
- Bootstrap fileinput.js,最好用的文件上传组件
本篇介绍如何使用bootstrap fileinput.js(最好用的文件上传组件)来进行图片的展示,上传,包括springMVC后端文件保存. 一.demo 二.插件引入 <link ty ...
- 基于Node的React图片上传组件实现
写在前面 红旗不倒,誓把JavaScript进行到底!今天介绍我的开源项目 Royal 里的图片上传组件的前后端实现原理(React + Node),花了一些时间,希望对你有所帮助. 前端实现 遵循R ...
- Web Uploader - 功能齐全,完美兼容 IE 的上传组件
文件上传是网站和 Web 应用程序的常用功能,一直没有一款完美的文件上传组件,因此让很多开发人员碰到头疼的浏览器兼容问题. WebUploader 是由 Baidu FEX 团队开发的一款以 HTML ...
- Atitit..文件上传组件选型and最佳实践总结(2)----断点续传
Atitit..文件上传组件选型and最佳实践总结(2)----断点续传 1. 断点续传的原理 1 2. 如何判断一个插件/控件是否支持断点续传?? 1 3. 常用的组件选型结果::马 1 4. 自定 ...
- 异步文件上传组件 Uploader
Uploader是非常强大的异步文件上传组件,支持ajax.iframe.flash三套方案,实现浏览器的全兼容,调用非常简单,内置多套主题支持 和常用插件,比如验证.图片预览.进度条等,广泛应用于淘 ...
随机推荐
- Git 分支管理 不使用Fast forward模式进行合并 分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的comm ...
- JS 上拉加载
$(document).ready( function(){ $contentLoadTriggered = false; $("#mainDiv").scroll(functio ...
- codevs 2314 数学作业
2314 数学作业 2011年省队选拔赛湖南 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 小 C 数学成绩优异 ...
- 4.Python的不堪一击到初学乍练(列表,元组)
Python(列表,元组) 一.列表 列表初识 列表是python的基础数据类型之一,其他编程语言也有类似的数据类型. 比如JS中的数组, java中的数组等等,它是以[ ]括起来, 每个元素用&qu ...
- Oracle共享服务器的连接模式
一般Oracle数据库安装默认都是选择专用服务器模式的连接方式,但实际上Oracle也支持共享服务器的连接模式,不过这种在实际生产中见到的很少,我个人只在一些医院行业的客户生产环境中见到过这类配置. ...
- Hexo - 记录一次Pages服务部署失败的原因
问题与分析 某天忽然发现,一直运行得好好的Pages服务部署失败了,GitHub Pages报错如下: Your site is having problems building: The tag c ...
- sql 查询重复数据
select user_name,count(*) as count from comm_user group by user_name having count>1;
- Leetcode:单调数列
题目 如果数组是单调递增或单调递减的,那么它是单调的. 如果对于所有 i <= j,A[i] <= A[j],那么数组 A 是单调递增的. 如果对于所有 i <= j,A[i]> ...
- Django框架之MVT(2)
Django框架之MVT 1. MVT模型 - module:模型,和数据库相关的 - template:模板,存放html文件,模板语法(目的是将变量如果巧妙的嵌入到h ...
- redis最佳实践
总结: String类型的value(string/list/set/hash)使用StringRedisTemplate 其他类型的value(string/list/set/hash/object ...