概述
对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上。
1、传统的Web应用
2、AJAX
补充:
1、同步异步描述:
利用ajax发请求就在于它的异步方式,偷偷发送,不影响页面的任何效果;
如果采用同步发送,就没有什么意义了。
2、兼容性问题:
1)ie8以下的浏览器并没有XMLHTTPRequest对象(浏览器的对象,广义上的,是现在浏览器都支持的),所以不能发Ajax操作,这就涉及到兼容性的问题;
但早期IE有一种对象可以替代XMLHTTPRequest,他就是ActiveXObject。
2)jQuery1.x版本具有上下兼容性,2.x以上版本不支持,果断的放弃了兼容性问题;
所以,利用jQuery发Ajax请求,如果考虑兼容性问题,就需要使用1.x版本的Query,它是对ActiveXObject的上层封装。
3、拓展:
alert、XMLHTTPRequest都是属于windows的,全称是windows.;
alert() = windows.alert() XMLHTTPRequest() = windows.XMLHTTPRequest() windows['XMLHTTPRequest']
原生AJAX
Ajax主要就是使用 【XmlHttpRequest】对象来完成请求的操作,该对象在主流浏览器中均存在(除早起的IE),Ajax首次出现IE5.5中存在(ActiveX控件)。
1、XmlHttpRequest对象介绍
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...
2、跨浏览器支持
- XmlHttpRequest
IE7+, Firefox, Chrome, Opera, etc. - ActiveXObject("Microsoft.XMLHTTP")
IE6, IE5
基于原生AJAX - Demo
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>XMLHttpRequest - Ajax请求</h1> <input type="button" onclick="XmlGetRequest();" value="Get发送请求" /> <input type="button" onclick="XmlPostRequest();" value="Post发送请求" /> <script src="/statics/jquery-1.12.4.js"></script> <script type="text/javascript"> // 解决原生ajax的浏览器版本兼容性问题 function GetXHR(){ var xhr = null; if(XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } return xhr; } function XhrPostRequest(){ var xhr = GetXHR(); // 定义回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 已经接收到全部响应数据,执行以下操作 var data = xhr.responseText; console.log(data); } }; // 指定连接方式和地址----文件方式 xhr.open('POST', "/test/", true); // 设置请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); // 发送请求 xhr.send('n1=1;n2=2;'); } function XhrGetRequest(){ var xhr = GetXHR(); // 定义回调函数 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 已经接收到全部响应数据,执行以下操作 var data = xhr.responseText; console.log(data); } }; // 指定连接方式和地址----文件方式 xhr.open('get', "/test/", true); // 发送请求 xhr.send(); } </script> </body> </html>
注意事项:
兼容性(加上下面的代码):
function GetXHR(){ var xhr = null; if(XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } return xhr; }
发普通数据(字符串,或key,value类型):
实例:
urls:
# path('ajax$', views.ajax), X path不支持^ url('^ajax$', views.ajax), url('^ajax_json$', views.ajax_json),
views:
################原生ajax############# def ajax(request): return render(request, 'day24-app06/ajax.html') def ajax_json(request): print("request.POST", request.POST) # 得到的空对象:<QueryDict: {}>,post提交传字符串类型, js需要加入请求头 # xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); # < QueryDict: {' pwd': ['akaedu'], 'user': ['uson']} > ret = {'status': True, 'data': request.POST.get('user')} # 返回给前端 import json return HttpResponse(json.dumps(ret)) # HttpResponse继承基类:HttpResponseBase-->status, reason='Not Found' # return HttpResponse(json.dumps(ret), status=200, reason='Not Found')返回更多的数据
ajax.html(未考虑兼容性问题):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="原生Ajax" onclick="Ajax1();" /> <script> function Ajax1() { // 过程分析: // 创建XMLHttpRequest对象 // open(发送方式,发送地址,同步/异步发送) // send("数据1=value1; 数据2=value2") var xhr = new XMLHttpRequest(); // 无ie下的兼容性 // get方式 // xhr.open('get', '/cohui/ajax_json', true); 不写,默认是true // xhr.send({'code': 304, 'status': true}); X // xhr.send('name=uson; pwd=123'); // post方式, 后台接收 // 先忽略csrf_token xhr.open('post', '/cohui/ajax_json', true); // 还可以设置添加请求头 xhr.setRequestHeader('k1', 'v1'); // post 提交字符串类型,必须写上下面的请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); xhr.send('user=uson; pwd=akaedu'); // 前端接收返回回来的数据 // 当readystate值发生了变化,就会执行下面的函数,现在,给函数执行加入一个条件:接收完成打印信息 xhr.onreadystatechange = function(){ // 相当于一个回调函数 if(xhr.readyState == 4){ // 后台已经接收到全部请求数据,执行以下操作 var data = xhr.responseText; // 获取数据 // console.log(data); // {"status": true, "data": "uson"} // 字典,js不能取到,需要转成对象 data = JSON.parse(data); console.log(data); console.log(data.data); // uson } }; } </script> </body> </html>
ajax.html(考虑兼容性问题):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="原生Ajax" onclick="Ajax1();" /> <script> // 跨浏览器支持:https://www.cnblogs.com/wupeiqi/articles/5703697.html // 解决IE低版本浏览器兼容性问题 function getXHR(){ var xhr = null; if(XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } return xhr; } function Ajax1() { // 过程分析: // 创建XMLHttpRequest对象 // open(发送方式,发送地址,同步/异步发送) // send("数据1=value1; 数据2=value2") // 增加兼容性: var xhr = getXHR(); // get方式 // xhr.open('get', '/cohui/ajax_json', true); 不写,默认是true // xhr.send({'code': 304, 'status': true}); X // xhr.send('name=uson; pwd=123'); // post方式, 后台接收 // 先忽略csrf_token xhr.open('post', '/cohui/ajax_json', true); // 还可以设置添加请求头 xhr.setRequestHeader('k1', 'v1'); // post 提交字符串类型,必须写上下面的请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); xhr.send('user=uson; pwd=akaedu'); // 前端接收返回回来的数据 // 当readystate值发生了变化,就会执行下面的函数,现在,给函数执行加入一个条件:接收完成打印信息 xhr.onreadystatechange = function(){ // 相当于一个回调函数 if(xhr.readyState == 4){ // 后台已经接收到全部请求数据,执行以下操作 var data = xhr.responseText; // 获取数据 // console.log(data); // {"status": true, "data": "uson"} // 字典,js不能取到,需要转成对象 data = JSON.parse(data); console.log(data); console.log(data.data); // uson } }; } </script> </body> </html>
小结:
1、基于原生Ajax发POST请求,如果是普通数据类型,一定要加上请求头,否则后台不认识,无法解析send中的内容数据(字符串或key,value类型)。
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
上传文件(特殊类型的数据):
实例:
urls:
#############基于XML实现文件上传############# url('^upload$', views.upload),
views:
#############基于XML实现文件上传############# def upload(request): if request.method == "POST": username = request.POST.get('username') fafile = request.FILES.get('fafile') print(fafile, username) # 8月续费计划.xlsx uson # 循环接收文件chunks import os upload_path = os.path.join('static/upload/' + fafile.name) with open(upload_path, 'wb') as f: for item in fafile.chunks(): # 也可以直接用fafile迭代 f.write(item) # return redirect('/cohui/upload') # 下面方法:图片预览,指定路径 # upload必须放进静态目录下 ret = {'path': upload_path} import json return HttpResponse(json.dumps(ret)) return render(request, 'day24-app06/upload.html')
upload.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .main{ width: 100px; height: 40px; background-color: dodgerblue; color: white; position: relative; margin-bottom: 20px; } .file{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; /* 让原生的上传按钮在文字上面z-index,并使他的透明度opacity为0,即隐藏 */ opacity: 0; z-index: 100; cursor: pointer; } .upload{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 90; text-align: center; line-height: 40px; /*cursor: pointer;*/ } </style> </head> <body> <div class="main"> <input id="fafa" class="file" type="file" name="fafa" /> <a class="upload">上传</a> </div> <input type="button" value="XHR文件上传提交" onclick="xhrAjax();"> <div class="picPreview"></div> <script src="/static/jquery-1.12.4.js"></script> <script> // XML 原生ajax上传 function xhrAjax() { // 获取文件对象,类似于val,text var file_obj = document.getElementById('fafa').files[0]; // 第一个文件 // 发送的是对象,send() 不能直接发送对象类型 var fd = new FormData(); // 相当于form表单对象 fd.append('username', 'uson'); fd.append('fafile', file_obj); // 对象加进去,这时无需设置请求头了 var xhr = new XMLHttpRequest(); // 实例化 xhr.open('post', '/cohui/upload', true); // 设置提交到的url xhr.onreadystatechange = function () { if(xhr.readyState == 4){ // 接收完毕, 获取数据并转换成对象 var obj= JSON.parse(xhr.responseText); // 图片预览 // 每次预览前清空预览缓存 $('.picPreview').empty(); // 创建img标签 指定src路径属性 var imgTag = document.createElement('img'); imgTag.src = '/' + obj.path; $('.picPreview').append(imgTag); } }; //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); 无需设置请求头 // csrf_token的添加 xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')); // 依赖于jquery.cookie.js xhr.send(fd); } </script> </body> </html>
小结:
1、由于send不能直接发送对象obj,只能发送字符串类型,所以上传文件需要用到新知识:Formdata方法,不支持低版本的IE浏览器;
var fd = new FormData(); // 相当于form表单对象 fd.append('username', 'uson'); fd.append('fafile', file_obj); xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')); // 依赖于jquery.cookie.js xhr.send(fd); // 不用设置下面的那个请求头了 //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
jQuery Ajax
jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能。
- jQuery 不是生产者,而是大自然搬运工。
- jQuery Ajax本质 XMLHttpRequest 或 ActiveXObject
注:2.+版本不再支持IE9以下的浏览器
jQuery Ajax 方法列表
jQuery.get(...) 所有参数: url: 待载入页面的URL地址 data: 待发送 Key/value 参数。 success: 载入成功时回调函数。 dataType: 返回内容格式,xml, json, script, text, html jQuery.post(...) 所有参数: url: 待载入页面的URL地址 data: 待发送 Key/value 参数 success: 载入成功时回调函数 dataType: 返回内容格式,xml, json, script, text, html jQuery.getJSON(...) 所有参数: url: 待载入页面的URL地址 data: 待发送 Key/value 参数。 success: 载入成功时回调函数。 jQuery.getScript(...) 所有参数: url: 待载入页面的URL地址 data: 待发送 Key/value 参数。 success: 载入成功时回调函数。 jQuery.ajax(...) 部分参数: url:请求地址 type:请求方式,GET、POST(1.9.0之后用method) headers:请求头 data:要发送的数据 contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8") async:是否异步 timeout:设置请求超时时间(毫秒) beforeSend:发送请求前执行的函数(全局) complete:完成之后执行的回调函数(全局) success:成功之后执行的回调函数(全局) error:失败之后执行的回调函数(全局) accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型 dataType:将服务器端返回的数据转换成指定类型 "xml": 将服务器端返回的内容转换成xml格式 "text": 将服务器端返回的内容转换成普通文本格式 "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。 "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式 "json": 将服务器端返回的内容转换成相应的JavaScript对象 "jsonp": JSONP 格式 使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数 如果不指定,jQuery 将自动根据HTTP包MIME信息返回相应类型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string converters: 转换器,将服务器端的内容根据指定的dataType转换类型,并传值给success回调函数 $.ajax({ accepts: { mycustomtype: 'application/x-some-custom-type' }, // Expect a `mycustomtype` back from server dataType: 'mycustomtype' // Instructions for how to deserialize a `mycustomtype` converters: { 'text mycustomtype': function(result) { // Do Stuff return newresult; } }, });
基于jQueryAjax - Demo
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <p> <input type="button" onclick="XmlSendRequest();" value='Ajax请求' /> </p> <script type="text/javascript" src="jquery-1.12.4.js"></script> <script> function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'GET', dataType: 'text', success: function(data, statusText, xmlHttpRequest){ // 如果不想要它默认返回的数据,可以用xmlHttpRequest对象自定制,.responseText等方法 console.log(data); } }) } </script> </body> </html>
发普通数据(字符串,或key,value类型):
urls/views/html:
这里不做重述(忘记了?)
上传文件(特殊类型的数据):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .main{ width: 100px; height: 40px; background-color: dodgerblue; color: white; position: relative; margin-bottom: 20px; } .file{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; /* 让原生的上传按钮在文字上面z-index,并使他的透明度opacity为0,即隐藏 */ opacity: 0; z-index: 100; cursor: pointer; } .upload{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 90; text-align: center; line-height: 40px; /*cursor: pointer;*/ } </style> </head> <body> <div class="main"> <input id="fafa" class="file" type="file" name="fafa" /> <a class="upload">上传</a> </div> <!-- 方式1 form上传 --> <!-- 跳过 --> <input type="button" value="Jquery文件上传提交" onclick="jqSubmit();"> <div class="picPreview"></div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> // jquery上传 function jqSubmit() { var file_obj = document.getElementById('fafa').files[0]; var fd = new FormData(); // 相当于form表单对象 fd.append('username', 'uson'); fd.append('fafile', file_obj); $.ajax({ url: '/cohui/upload', type: 'POST', headers: {'X-CSRFtoken': $.cookie('csrftoken')}, data: fd, // 字符串类型 // TypeError: Illegal invocation, 加上下面的两行 processData: false, //tell jQuery not to process the data不对数据中的对象进行格式转换 contentType: false, // tell jQuery not to set contentType 不序列化json数据 // 分析: // processData:默认为true,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型 // contentType:“application/json” true必须是json数据, 'xx','oo' 非json数据,所以false success: function (args, a1, a2) { // console.log(args); // console.log(a1); // success console.log(a2); // 原生对象 // 图片预览 // 每次预览前清空预览缓存 $('.picPreview').empty(); // 创建img标签 指定src路径属性 var imgTag = document.createElement('img'); imgTag.src = '/' + obj.path; $('.picPreview').append(imgTag); } }); } </script> </body> </html>
“伪”AJAX
由于HTML标签的iframe标签具有局部加载内容的特性,所以可以使用其来伪造Ajax请求。
1、load
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div> <p>请输入要加载的地址:<span id="currentTime"></span></p> <p> <input id="url" type="text" /> <input type="button" value="刷新" onclick="LoadPage();"> </p> </div> <div> <h3>加载页面位置:</h3> <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe> </div> <script type="text/javascript"> window.onload= function(){ var myDate = new Date(); document.getElementById('currentTime').innerText = myDate.getTime(); }; function LoadPage(){ var targetUrl = document.getElementById('url').value; document.getElementById("iframePosition").src = targetUrl; } </script> </body> </html>
发普通数据(字符串,或key,value类型):
urls:
#################伪ajax############## url('^iframe', views.iframe),
views:
#################伪ajax############## def iframe(request): if request.method == "POST": import time time.sleep(3) # ajax提交数据后,等待后台数据回复返回后,才会加载到iframe中 # 所以,可以通过onload来获取iframe返回的时机,从而获取数据 ret = {'status': True, 'data': request.POST.get('username')} # 返回给前端 import json return HttpResponse(json.dumps(ret)) return render(request, 'day24-app06/iframe.html')
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/cohui/iframe" method="post" target="ifm"> {% csrf_token %} <!-- iframe的name属性与form的target属性相互关系:form提交表单数据到iframe中,页面不刷新,其他内容不改变 --> <!-- <iframe name="ifm" src="http://www.cohui.top"></iframe> --> <!-- 方式1 <iframe name="ifm" onload="ifr();"></iframe> --> <!-- 方式2: 给submit一个点击事件,再去获取iframe的加载事件,不报错 --> <iframe name="ifm" id="ifm"></iframe> <!-- #document --> <input type="text" name="username" > <input type="text" name="email" > <input type="submit" value="Form提交" onclick="ifrm();" > </form> <script src="/static/jquery-1.12.4.js"></script> <script> // 方式1: function ifr() { console.log(123); // 从上到下执行,先会找到 ifr()这个函数,但,这个函数在未提交前,还没执行呢,提前加载自然报错 // Uncaught ReferenceError: ifr is not defined at HTMLIFrameElement.onload // 所以这种方式不太好 } // 方式2; function ifrm() { // 获取iframe对象 console.log(12); // 点击提交后,立即打印 $('#ifm').load(function(){ // 不是onload (onload是一个事件),是load (load是一个函数) // 获取数据 console.log(13); // load:用来接收返回的数据,后台有数据返回,才会执行这个函数 var doc = $('#ifm').contents(); console.log(doc); // jQuery.fn.init [document, prevObject: jQuery.fn.init(1), context: document] var data = doc.find('body').text(); console.log(data); // {"status": true, "data": "123"} var obj = JSON.parse(data); console.log(obj); // 转成对象 }); } </script> </body> </html>
上传文件(特殊类型的数据):
urls:
url('^upload$', views.upload),
views:
##################基于XML实现文件上传################ def upload(request): if request.method == "POST": username = request.POST.get('username') fafile = request.FILES.get('fafile') print(fafile, username) # 8月续费计划.xlsx uson # 循环接收数据chunks import os upload_path = os.path.join('static/upload/' + fafile.name) with open(upload_path, 'wb') as f: for item in fafile.chunks(): f.write(item) # return redirect('/cohui/upload') # 图片预览,指定路径 # upload必须放进静态目录下 ret = {'path': upload_path} import json return HttpResponse(json.dumps(ret)) return render(request, 'day24-app06/upload.html')
html(直接预览上传):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .main{ width: 100px; height: 40px; background-color: dodgerblue; color: white; position: relative; margin-bottom: 20px; } .file{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; /* 让原生的上传按钮在文字上面z-index,并使他的透明度opacity为0,即隐藏 */ opacity: 0; z-index: 100; cursor: pointer; } .upload{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 90; text-align: center; line-height: 40px; /*cursor: pointer;*/ } </style> </head> <body> <div class="main"> <input id="fafa" class="file" type="file" name="fafa" /> <a class="upload">上传</a> </div> <!-- 方式1 form上传 --> <!-- 跳过 --> <!-- iframe 伪ajax上传 --> <form action="/cohui/upload" method="post" target="ifm" enctype="multipart/form-data"> {% csrf_token %} <iframe name="ifm" id="ifm" style="display: none;"></iframe> <!-- #document --> // <input type="file" name="fafile" onchange="changeSubmit(this);" >绑定事件也是可以的==》function changeSubmit(ths) {} <!--第二种--> <input type="file" name="fafile" > <!--第一种--> ==> $('input[name="fafile"]').change(function () {}) </form> <div class="picPreview"></div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> // iframe 伪ajax上传, 不点提交按钮,直接预览上传 $('input[name="fafile"]').change(function () { // 不能用onchange,因为它不是函数// 先绑定一个onload事件 // 再form submit() $('#ifm').load(function () { // 加载框架,获取内容 console.log(456); var data = $(this).contents().find('body').text(); var obj = JSON.parse(data); // 预览前清空内容 $('.picPreview').empty(); // 图片预览 var imgTag = document.createElement('img'); imgTag.src = '/' + obj.path; $('.picPreview').append(imgTag); }); // $(ths).submit(); // this --> file的input对象 X console.log(123); // 先123,后台返回数据才456 $('form').submit(); }) </script> </body> </html>
html(提交上传):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .main{ width: 100px; height: 40px; background-color: dodgerblue; color: white; position: relative; margin-bottom: 20px; } .file{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; /* 让原生的上传按钮在文字上面z-index,并使他的透明度opacity为0,即隐藏 */ opacity: 0; z-index: 100; cursor: pointer; } .upload{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 90; text-align: center; line-height: 40px; /*cursor: pointer;*/ } </style> </head> <body> <div class="main"> <input id="fafa" class="file" type="file" name="fafa" /> <a class="upload">上传</a> </div> <!-- iframe 伪ajax上传 --> <form action="/cohui/upload" method="post" target="ifm" enctype="multipart/form-data"> {% csrf_token %} <iframe name="ifm" id="ifm" style="display: none;"></iframe> <!-- #document --> <input type="file" name="fafile" /> <input type="submit" value="Iframe提交" onclick="iframeSubmit();" /> </form> <div class="picPreview"></div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> // iframe 伪ajax上传 + 图片预览 function iframeSubmit() { // 提交到iframe中,有一个load加载过程,后台什么时候返回数据,什么时候加载 $('#ifm').load(function () { // 后台返回数据就加载 var data = $(this).contents().find('body').text(); var obj = JSON.parse(data); console.log(obj.path); // upload/win10快捷键.jpg // 图片预览 // 每次预览前清空预览缓存 $('.picPreview').empty(); // 创建img标签 指定src路径属性 var imgTag = document.createElement('img'); imgTag.src = '/' + obj.path; $('.picPreview').append(imgTag); }) } </script> </body> </html>
小结:
1、提交表单共有4种方式:
1)form提交(刷新页面)
2)原生Ajax方式提交(不刷新页面)
3)jQuery方式提交(不刷新页面)
4)伪Ajax方式提交(不刷新页面)
2、上传文件(对象类型)特殊类型的数据,如何选择上述Ajax的几种方式?
原生Ajax方式提交和jQuery方式提交==>都依赖于FormData()类,而FormData对于IE低版本浏览器又不兼容;iframe支持所有浏览器。
所以使用的优先级比较:iframe > jQuery(FormData) > XMLHttpRequest(FormData)
3、普通类型(字符串、key,value)的数据,如何选择上述Ajax的几种方式?
原生Ajax方式提交和jQuery方式提交==>都依赖于FormData()类,而FormData对于IE低版本浏览器又不兼容;iframe支持所有浏览器。
所以使用的优先级比较:jQuery(FormData) > XMLHttpRequest(FormData) > iframe
4、iframe:里面包含的是#document,即一个上下文或空间管理,嵌套html,用.text()无法获取到数据,这里用到的是:contents()方法获取内容;
$(...).contents().find('body').text();
5、原生Ajax设置csrf的请求头方式:
xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')); // 依赖于jquery.cookie.js
跨域AJAX
序列化
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
1、serializers
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
2、json.dumps
import json #ret = models.BookType.objects.all().values('caption') ret = models.BookType.objects.all().values_list('caption') ret=list(ret) result = json.dumps(ret)
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:
import json from datetime import date from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return o.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field) # ds = json.dumps(d, cls=JsonCustomEncoder)
后记:
form表单提交,页面肯定会刷新,ajax无法跳转
None:没有长度==>len()
Ipv4与Ipv6的认识:
Ipv4:32位,分4段:每段8位(0-255):192.168.1.6 Ipv6:128位,分8段:FE80::DE4F(共8段,中间全是0可以省略不写::)
html模板语言中的计数序号问题:
{% for row in user_list%} {{forloop.counter}} 从1开始计数 {{forloop.counter0}} 从0开始计数 {{forloop.revcounter}} 倒序 {{forloop.revcounter0}} 倒序 {{forloop.last}} 是否是最后一次循环(返回true) {{forloop.first}} 是否是第一个循环 {{forloop.parentloop}} 用于嵌套循环,返回上一个循环的值 {% endfor%}
循环事件里面不能用id选择器(不能重复),要用class选择器
ajax打包数据发送到后台:
找到form标签==>$().serialize()====》data,会把整个form里面的值发到后台。
Ajax的返回问题:
Ajax的后台返回return 只能是HttpResponse或render(render返回html,字符串取值麻烦,列表、字典类的数据类型反序列化成对象,取值方便),但不可以是redirect,因为Ajax无法跳转页面
建议:永远返回一个字典,取值容易。
403 Forbidden (CSRF token missing or incorrect解决办法: