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'})
    "

    {{ name }}

    " -->> "

    v1

    " 只能返回字符串给用户
    不能redirect()
    用户 <<<<< 字符串

  • ajax只发送数据不涉及表单时,解决csrf_token

    引入cookie,在ajax中将cookie中的csrftoken添加至请求头中

    $.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内的标签

# target将form与iframe绑定




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

兼容性好





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巧妙实现跨域请求:

  1. 创建script标签

    var tag = document.createElement('script');

  2. src=远程地址

    tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';

  3. 将标签添加进header,随后移除

    document.head.appendChild(tag);
    document.head.removeChild(tag);

  4. 返回的数据必须是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



  • 详细参数

http://kindeditor.net/docs/option.html

2.文件上传

  • 文件上传,多文件上传,文件空间管理

3.XSS攻击(过滤的函数或类)

下节课说...

使用kindeditor会隐藏原来的textarea标签,而如果该标签为required,提交时浏览器会报错

解决办法:

  1. form表单添加novalidate属性,但会导致所有验证都不能用,不建议

  2. 取消该标签的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

posted @ 2020-07-05 23:33  Jerome12138  阅读(222)  评论(0)    收藏  举报