Python学习笔记Day24 - Ajax
初识Ajax
验证输入信息
悄悄地提交,不刷新页面
$('i1').click(function(){
$.ajax({
url: '/host',
type: "POST",
data: {'k1': 123,'k2': "root",'k4': JSON.stringfy({'k1': 'v'})}, // 要提交的数据
// .stringfy() 将字典序列化成字符串
// traditional:true // 使发送的data中可以接收列表数据'k3':[1,2,3]
// data:$('#add_form').serialize(), // 自动将form表单中的数据打包发送,上传文件看下面
dataType:'JSON', // 自动将接收到的data反序列化成obj返回
success: function(data){ // 此处data为接收到返回的httpRes信息,可传obj
// 服务器返回信息后自动触发
// data是服务器端返回的字符串, 如果用dataType:'JSON', 传的参数是obj对象
// var obj = JSON.parse(data); // json将字符串反序列化成字典 #.stringfy()序列化
if (obj.status){
location.reload(); // 刷新
location.href = "某个地址" // 跳转
}else{
$('#error_msg').text(obj.error) // 将收到的错误信息传给error_msg标签
}
},
error:function(){
...
//后台未接收到请求或未返回数据等未知错误
}
})
})
-
其他写法:(不推荐)
$.get(url='',data='',success='function(){}') $.post(url='',data='',success='function(){}')
-
建议:永远让服务器端返回一个字典
ret={'status':True,'error':None,'data':None} return HttpResponse(json.dumps(ret)) #json将字典序列化成字符串
-
ajax返回数据推荐用HttpResponse
提交 -> url -> 函数或类中的方法 HttpResponse('{}') render(request, 'index.html', {'name': 'v1'}) "<h1>{{ name }}</h1>" -->> "<h1>v1</h1>" 只能返回字符串给用户 不能redirect() 用户 <<<<< 字符串
-
ajax只发送数据不涉及表单时,解决csrf_token
引入cookie,在ajax中将cookie中的csrftoken添加至请求头中 <script src="/static/jquery.cookie.js"></script> $.ajax({ ... headers: {"X-CSRFToken": $.cookie('csrftoken')}, ... })
Ajax发送数据
大部分采用XMLHttpRequest,但IE只支持ActiveXObject
原生Ajax
-
创建XMLHttpRequest或ActiveXObject对象
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(); }
基于jQuery的Ajax
jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能
jQuery 不是生产者,而是大自然搬运工。
jQuery Ajax本质: XMLHttpRequest 或 ActiveXObject
注:2.+版本不再支持IE9以下的浏览器
$.ajax({
url: '/upload_file/',
type: 'POST',
data: fd,
success:function(arg,a1,a2){
console.log(arg);
console.log(a1);
console.log(a2); # a2包含一个xhr对象
}
})
伪Ajax操作(iframe)
由于HTML标签的iframe标签具有局部加载内容的特性,所以可以使用其来伪造Ajax请求。
服务端返回时,触发iframe的onload事件,并将数据放在iframe的#document对象中
也可自定义onload事件,使用$('#ifm1').contents()获取iframe内的标签
<form action="/ajax_json/" method="POST" target="ifm1"> # target将form与iframe绑定
<iframe id="ifm1" name="ifm1" ></iframe>
<input type="text" name="username" />
<input type="text" name="email" />
<input type="submit" onclick="sumitForm();" value="Form提交"/>
</form>
function sumitForm(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
})
}
三种方式使用的时机
如果发送的是【普通数据】 -> jQuery,XMLHttpRequest,iframe
如果发送的是【文件】 -> iframe,jQuery(FormData),XMLHttpRequest(FormData)
文件上传(预览)
上传按钮的input框本身不能直接style修改美化,只能通过relative伪覆盖添加新的标签进行美化
上传文件三种方式:
1. iframe
兼容性好
<form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
<iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
<input type="file" name="fafafa" onchange="changeUpalod();" />
<input type="submit" onclick="iframeSubmit();" value="Form提交"/>
</form>
function iframeSubmit(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
// 实现预览
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/" + obj.data;
$('#preview').append(imgTag);
})
}
2. jQuery(FormData)
function jqSubmit(){
// ajax上传文件必须通过FormData对象传输数据
var formdata = new FormData();
formdata.append('username', $('#username').val());
formdata.append('psd', $('#password').val());
formdata.append('file', $('#file')[0].files[0]);
$.ajax({
url: '/upload_file/',
type: 'POST',
headers: { "X-CSRFToken": $.cookie('csrftoken') },
data: formdata,
processData: false, // 不处理数据(文件上传必须)
contentType: false, // 不设置内容类型,按原格式传输(文件上传必须)
success:function(arg,a1,a2){
console.log(arg);
console.log(a1);
console.log(a2);
}
})
}
3. XMLHttpRequest(FormData)
function xhrSubmit(){
// $('#fafafa')[0] // 获取input上传的文件对象
var file_obj = document.getElementById('fafafa').files[0];
var fd = new FormData(); // 创建FormData对象
fd.append('username','root'); // 添加普通数据,key-value
fd.append('fafafa',file_obj); // 添加文件对象,key-obj
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload_file/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 接收完毕
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.send(fd);
}
图片验证码 + Session
1. GET访问页面
-> 创建图片并返回给用户
=> 用Pillow模块创建一张图片,并在图片中写入随机字符串(封装成check_code.py模块,返回img对象和验证字符串strs)(依赖字体文件)
img, code = creat_validate_code()
=> 将img写入内存
stream = BytesIO()
img.save(stream,'PNG')
=> 读取内存中的图片并显示
data = stream.getValue()
HttpResponse(data)
-> session存放验证码
=> 将code写入session
request.session['CheckCode'] = code
2. POST提交数据
-> 比对验证码
if request.session['CheckCode'].upper() == request.POST.get('check_code').upper();
...
-> 更换验证码
绑定点击事件 onclick="changeCheckCode(this);"
ths.src = ths.src + '?' # 采用地址后面加?的方式,更换地址重新获取验证码
JSONP - 最广泛的跨域请求方式
(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性实现跨域请求
import requests
response = request.get('http://www.baidu.com')
response = request.post('http://www.baidu.com')
# print(response.content) # 字节格式的文本
response.encoding = 'utf-8' # 指定编码
print(response.text) # 文本内容(经编码后的字符串)
print(response.headers) # 响应头
print(response.cookies) # 所有cookies
return render(request, 'req.html',{'result': response.text})
由于浏览器具有同源策略(阻止Ajax请求,但无法阻止)
JSONP使用js巧妙实现跨域请求:
-
创建script标签
var tag = document.createElement('script');
-
src=远程地址
tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
-
将标签添加进header,随后移除
document.head.appendChild(tag); document.head.removeChild(tag);
-
返回的数据必须是js格式
必须提前写好函数才能解析返回的js代码,可将函数名用callback参数传给url
JSONP只能发GET请求
利用ajax实现JSONP请求:
$.ajax({
url: 'http://www.jxntv.cn/data/jmd-jxtv2.html',
type: 'POST',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'list' # 传递函数名
})
原理同上
还有CORS方式跨域请求,直接将域名加白名单
编辑框
CKEditor,UEEditor,TinyEditor,KindEditor(***)
1.基本使用
-
文件夹说明
├── asp -> asp示例 ├── asp.net -> asp.net示例 ├── attached -> 空文件夹,放置关联文件attached ├── examples -> HTML示例 ├── jsp -> java示例 ├── lang -> 支持语言 ├── license.txt -> License ├── php -> PHP示例 ├── plugins -> KindEditor内部使用的插件 ├── themes -> KindEditor主题 ├── kindeditor-all-min.js -> 全部JS 包含插件(压缩) ├── kindeditor-all.js -> 全部JS 包含插件(未压缩) ├── kindeditor-min.js -> 仅KindEditor JS(压缩) └── kindeditor.js -> 仅KindEditor JS(未压缩)
-
HTML
<textarea name="content" id="content"></textarea> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/plugins/kind-editor/kindeditor-all.js"></script> <script> $(function () { initKindEditor(); }); function initKindEditor() { var kind = KindEditor.create('#content', { width: '100%', // 文本框宽度(可以百分比或像素) height: '300px', // 文本框高度(只能像素) minWidth: 200, // 最小宽度(数字) minHeight: 400 // 最小高度(数字) }); } </script>
-
详细参数
http://kindeditor.net/docs/option.html
2.文件上传
- 文件上传,多文件上传,文件空间管理
3.XSS攻击(过滤的函数或类)
下节课说...
使用kindeditor会隐藏原来的textarea标签,而如果该标签为required,提交时浏览器会报错
解决办法:
-
form表单添加novalidate属性,但会导致所有验证都不能用,不建议
-
取消该标签的required
作业
主站:
http://127.0.0.1:8000/ 博客首页
http://127.0.0.1:8000/zhaofan/1.html 某人的某篇博客
个人博客:
http://127.0.0.1:8000/zhaofan.html 某人的博客
http://127.0.0.1:8000/zhaofan/tag/python.html 某人的博客筛选
http://127.0.0.1:8000/zhaofan/catetory/mvc.html 某人的博客筛选
http://127.0.0.1:8000/zhaofan/date/2011-11.html 某人的博客筛选
个人后台管理:
http://127.0.0.1:8000/backend/base-info.html
http://127.0.0.1:8000/backend/tag.html
http://127.0.0.1:8000/backend/category.html
http://127.0.0.1:8000/backend/article.html
http://127.0.0.1:8000/backend/add-article.html