转载自:http://www.cnblogs.com/yuanchenqi/articles/7638956.html

一、Ajax准备知识:json

什么是json?

定义:

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

讲json对象,不得不提到JS对象:

json字符串支持的数据类型:

'1'、'"hello"'、'true'、'[1,"abc"]'、'{"name":"abc"}'、'null'

合格的json对象:

["one", "two", "three"]

{ "one": 1, "two": 2, "three": 3 }

{"names": ["张三", "李四"] }

[ { "name": "张三"}, {"name": "李四"} ] 

不合格的json对象:

{ name: "张三", 'age': 32 }                     // 属性名必须使用双引号

[32, 64, 128, 0xFFF] // 不能使用十六进制值

{ "name": "张三", "age": undefined }            // 不能使用undefined

{ "name": "张三",
"birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
"getName": function() {return this.name;} // 不能使用函数和日期对象
}  

stringfy和parse方法

JSON.parse():     用于将一个 JSON 字符串转换为 JavaScript 对象 
eg:
console.log(JSON.parse('{"name":"Yuan"}'));
console.log(JSON.parse('{name:"Yuan"}')) ; // 错误
console.log(JSON.parse('[12,undefined]')) ; // 错误 JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 
eg: console.log(JSON.stringify({'name':"egon"})) ;

和XML的比较

JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。

JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。

XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。

用XML表示中国部分省市数据如下:
<?xml version="1.0" encoding="utf-8"?>
<country>
<name>中国</name>
<province>
<name>黑龙江</name>
<cities>
<city>哈尔滨</city>
<city>大庆</city>
</cities>
</province>
<province>
<name>广东</name>
<cities>
<city>广州</city>
<city>深圳</city>
<city>珠海</city>
</cities>
</province>
<province>
<name>台湾</name>
<cities>
<city>台北</city>
<city>高雄</city>
</cities>
</province>
<province>
<name>新疆</name>
<cities>
<city>乌鲁木齐</city>
</cities>
</province>
</country>

用JSON表示如下:

{
"name": "中国",
"province": [{
"name": "黑龙江",
"cities": {
"city": ["哈尔滨", "大庆"]
}
}, {
"name": "广东",
"cities": {
"city": ["广州", "深圳", "珠海"]
}
}, {
"name": "台湾",
"cities": {
"city": ["台北", "高雄"]
}
}, {
"name": "新疆",
"cities": {
"city": ["乌鲁木齐"]
}
}]
}

可以看到,JSON 简单的语法格式和清晰的层次结构明显要比 XML 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用得带宽。

注意:

JSON格式取代了xml给网络传输带来了很大的便利,但是却没有了xml的一目了然,尤其是json数据很长的时候,我们会陷入繁琐复杂的数据节点查找中。
但是国人的一款在线工具 BeJson 、SoJson在线工具让众多程序员、新接触JSON格式的程序员更快的了解JSON的结构,更快的精确定位JSON格式错误。
 

二、Ajax简介

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

js实现的局部刷新:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title> <style>
.error{
color:red
}
</style>
</head>
<body> <form class="Form"> <p>姓名&nbsp;&nbsp;<input class="v1" type="text" name="username" mark="用户名"></p>
<p>密码&nbsp;&nbsp;<input class="v1" type="text" name="email" mark="邮箱"></p>
<p><input type="submit" value="submit"></p> </form> <script src="jquery-3.1.1.js"></script> <script> $(".Form :submit").click(function(){ flag=true; $("Form .v1").each(function(){ var value=$(this).val();
if (value.trim().length==0){
var mark=$(this).attr("mark");
var $span=$("<span>");
$span.html(mark+"不能为空!");
$span.prop("class","error");
$(this).after($span); setTimeout(function(){
$span.remove();
},800); flag=false;
return flag; }
});
return flag
}); </script> </body>
</html>

js实现的局部刷新

AJAX常见应用情景

当我们在百度中输入一个“老”字后,会马上出现一个下拉列表!列表中显示的是包含“传”字的4个关键字。

其实这里就使用了AJAX技术!当文件框发生了输入变化时,浏览器会使用AJAX技术向服务器发送一个请求,查询包含“传”字的前10个关键字,然后服务器会把查询到的结果响应给浏览器,最后浏览器把这4个关键字显示在下拉列表中。

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为zhangSan的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。

  • 整个过程中页面没有刷新,只是局部刷新了;
  • 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;

AJAX的优缺点

优点:

  • AJAX使用Javascript技术向服务器发送异步请求;
  • AJAX无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的局部,所以AJAX性能高;

三、jquery实现的Ajax

{% load staticfiles %}

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'JS/jquery-3.1.1.js' %}"></script>
</head>
<body> <button class="send_Ajax">send_Ajax</button> <script>
//$.ajax的两种使用方式: //$.ajax(settings);
//$.ajax(url,[settings]); $(".send_Ajax").click(function(){ $.ajax({
url:"/handle_Ajax/",
type:"POST",
data:{username:"Yuan",password:123}, success:function(data){
alert(data)
}, //=================== error============ error: function (jqXHR, textStatus, err) { // jqXHR: jQuery增强的xhr
// textStatus: 请求完成状态
// err: 底层通过throw抛出的异常对象,值与错误类型有关
console.log(arguments);
}, //=================== complete============ complete: function (jqXHR, textStatus) {
// jqXHR: jQuery增强的xhr
// textStatus: 请求完成状态 success | error
console.log('statusCode: %d, statusText: %s', jqXHR.status, jqXHR.statusText);
console.log('textStatus: %s', textStatus);
}, //=================== statusCode============
statusCode: {
'403': function (jqXHR, textStatus, err) {
console.log(arguments); //注意:后端模拟errror方式:HttpResponse.status_code=500
}, '400': function () {
}
} }) }) </script>
</body>
</html>

$.ajax参数

请求参数

######################------------data---------################

       data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式
(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。 function testData() {
$.ajax("/test",{ //此时的data是一个json形式的对象
data:{
a:1,
b:2
}
}); //?a=1&b=2
######################------------processData---------################ processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,
那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString()
,最后得到一个[object,Object]形式的结果。 ######################------------contentType---------################ contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。
用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,
比如contentType:"application/json",即向服务器发送一个json字符串:
$.ajax("/ajax_get",{ data:JSON.stringify({
a:22,
b:33
}),
contentType:"application/json",
type:"POST", }); //{a: 22, b: 33} 注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象 views.py: json.loads(request.body.decode("utf8")) ######################------------traditional---------################ traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]},
traditional为false会对数据进行深层次迭代;

响应参数

/*

dataType:  预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。
默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;
比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容
进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式
的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用
data Type。
dataType的可用值:html|xml|json|text|script
见下dataType实例 */

示例:

from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
# Create your views here. import json def login(request): return render(request,'Ajax.html') def ajax_get(request): l=['alex','little alex']
dic={"name":"alex","pwd":123} #return HttpResponse(l) #元素直接转成字符串alexlittle alex
#return HttpResponse(dic) #字典的键直接转成字符串namepwd
return HttpResponse(json.dumps(l))
return HttpResponse(json.dumps(dic))# 传到前端的是json字符串,要想使用,需要JSON.parse(data) //---------------------------------------------------
function testData() { $.ajax('ajax_get', {
success: function (data) {
console.log(data);
console.log(typeof(data));
//console.log(data.name);
//JSON.parse(data);
//console.log(data.name);
},
//dataType:"json",
}
)} 注解:Response Headers的content Type为text/html,所以返回的是String;但如果我们想要一个json对象
设定dataType:"json"即可,相当于告诉ajax方法把服务器返回的数据转成json对象发送到前端.结果为object
当然,
return HttpResponse(json.dumps(a),content_type="application/json") 这样就不需要设定dataType:"json"了。
content_type="application/json"和content_type="json"是一样的!

csrf跨站请求伪造

方式一:

$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

方式二:

<form>
{% csrf_token %}
</form><br><br><br>$.ajax({<br>...<br>data:{
"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val();
}<br>})

方式三:

<script src="{% static 'js/jquery.cookie.js' %}"></script>
$.ajax({
headers:{"X-CSRFToken":$.cookie('csrftoken')},
})

四、JS实现的ajax

AJAX核心(XMLHttpRequest

其实AJAX就是在Javascript中多添加了一个对象:XMLHttpRequest对象。所有的异步交互都是使用XMLHttpServlet对象完成的。也就是说,我们只需要学习一个Javascript的新对象即可。

var xmlHttp = new XMLHttpRequest();(大多数浏览器都支持DOM2规范)

注意,各个浏览器对XMLHttpRequest的支持也是不同的!为了处理浏览器兼容问题,给出下面方法来创建XMLHttpRequest对象:

function createXMLHttpRequest() {
var xmlHttp;
// 适用于大多数浏览器,以及IE7和IE更高版本
try{
xmlHttp = new XMLHttpRequest();
} catch (e) {
// 适用于IE6
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// 适用于IE5.5,以及IE更早版本
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){}
}
}
return xmlHttp;
}

使用流程

步骤1:  打开与服务器的连接(open方法)

当得到XMLHttpRequest对象后,就可以调用该对象的open()方法打开与服务器的连接了。open()方法的参数如下:

open(method, url, async):

  • method:请求方式,通常为GET或POST;
  • url:请求的服务器地址,例如:/ajaxdemo1/AServlet,若为GET请求,还可以在URL后追加参数;
  • async:这个参数可以不给,默认值为true,表示异步请求;
var xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "/ajax_get/?a=1", true); 

步骤2:  发送请求

当使用open打开连接后,就可以调用XMLHttpRequest对象的send()方法发送请求了。send()方法的参数为POST请求参数,即对应HTTP协议的请求体内容,若是GET请求,需要在URL后连接参数。

注意:若没有参数,需要给出null为参数!若不给出null为参数,可能会导致FireFox浏览器不能正常发送请求!

xmlHttp.send(null);

步骤3:  接收服务器响应

当请求发送出去后,服务器端就开始执行了,但服务器端的响应还没有接收到。接下来我们来接收服务器的响应。

XMLHttpRequest对象有一个onreadystatechange事件,它会在XMLHttpRequest对象的状态发生变化时被调用。下面介绍一下XMLHttpRequest对象的5种状态:

  • 0:初始化未完成状态,只是创建了XMLHttpRequest对象,还未调用open()方法;
  • 1:请求已开始,open()方法已调用,但还没调用send()方法;
  • 2:请求发送完成状态,send()方法已调用;
  • 3:开始读取服务器响应;
  • 4:读取服务器响应结束。

onreadystatechange事件会在状态为1、2、3、4时引发。

  下面代码会被执行四次!对应XMLHttpRequest的四种状态!

xmlHttp.onreadystatechange = function() {
alert('hello');
};

但通常我们只关心最后一种状态,即读取服务器响应结束时,客户端才会做出改变。我们可以通过XMLHttpRequest对象的readyState属性来得到XMLHttpRequest对象的状态。

xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
alert('hello');
}
};

其实我们还要关心服务器响应的状态码是否为200,其服务器响应为404,或500,那么就表示请求失败了。我们可以通过XMLHttpRequest对象的status属性得到服务器的状态码。

最后,我们还需要获取到服务器响应的内容,可以通过XMLHttpRequest对象的responseText得到服务器响应内容。

xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
alert(xmlHttp.responseText);
}
};

if 发送POST请求

<1>需要设置请求头:xmlHttp.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);注意 :form表单会默认这个键值对不设定,Web服务器会忽略请求体的内容。

<2>在发送时可以指定请求体了:xmlHttp.send(“username=yuan&password=123”)

JS实现ajax小结

/*
创建XMLHttpRequest对象;
调用open()方法打开与服务器的连接;
调用send()方法发送请求;
为XMLHttpRequest对象指定onreadystatechange事件函数,这个函数会在 XMLHttpRequest的1、2、3、4,四种状态时被调用; XMLHttpRequest对象的5种状态,通常我们只关心4状态。 XMLHttpRequest对象的status属性表示服务器状态码,它只有在readyState为4时才能获取到。 XMLHttpRequest对象的responseText属性表示服务器响应内容,它只有在
readyState为4时才能获取到! */

测试代码:

<h1>AJAX</h1>
<button onclick="send()">测试</button>
<div id="div1"></div> <script>
function createXMLHttpRequest() {
try {
return new XMLHttpRequest();//大多数浏览器
} catch (e) {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
} function send() {
var xmlHttp = createXMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var div = document.getElementById("div1");
div.innerText = xmlHttp.responseText;
div.textContent = xmlHttp.responseText;
}
}; xmlHttp.open("POST", "/ajax_post/", true);
//post: xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send(null); //post: xmlHttp.send("b=B");
} </script> #--------------------------------views.py
from django.views.decorators.csrf import csrf_exempt def login(request):
print('hello ajax')
return render(request,'index.html') @csrf_exempt #csrf防御
def ajax_post(request):
print('ok')
return HttpResponse('helloyuanhao')

实例(用户名是否已被注册)

7.1 功能介绍

在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。

客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!

7.2 案例分析

  • 页面中给出注册表单;
  • 在username表单字段中添加onblur事件,调用send()方法;
  • send()方法获取username表单字段的内容,向服务器发送异步请求,参数为username;
  • django 的视图函数:获取username参数,判断是否为“yuan”,如果是响应true,否则响应false

参考代码:

<script type="text/javascript">
function createXMLHttpRequest() {
try {
return new XMLHttpRequest();
} catch (e) {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
} function send() {
var xmlHttp = createXMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
if(xmlHttp.responseText == "true") {
document.getElementById("error").innerText = "用户名已被注册!";
document.getElementById("error").textContent = "用户名已被注册!";
} else {
document.getElementById("error").innerText = "";
document.getElementById("error").textContent = "";
}
}
};
xmlHttp.open("POST", "/ajax_check/", true, "json");
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var username = document.getElementById("username").value;
xmlHttp.send("username=" + username);
}
</script> //--------------------------------------------------index.html <h1>注册</h1>
<form action="" method="post">
用户名:<input id="username" type="text" name="username" onblur="send()"/><span id="error"></span><br/>
密 码:<input type="text" name="password"/><br/>
<input type="submit" value="注册"/>
</form> //--------------------------------------------------views.py
from django.views.decorators.csrf import csrf_exempt def login(request):
print('hello ajax')
return render(request,'index.html')
# return HttpResponse('helloyuanhao') @csrf_exempt
def ajax_check(request):
print('ok') username=request.POST.get('username',None)
if username=='yuan':
return HttpResponse('true')
return HttpResponse('false')

五、jQuery.serialize()

serialize()函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串

serialize()函数常用于将表单内容序列化,以便用于AJAX提交。

该函数主要根据用于提交有效表单控件的name和value,将它们拼接为一个可直接用于表单提交的文本字符串,该字符串已经过标准的URL编码处理(字符集编码为UTF-8)。

该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在<form>标签内的表单控件不会被提交、没有name属性的表单控件不会被提交、带有disabled属性的表单控件不会被提交、没有被选中的表单控件不会被提交。

与常规表单提交不一样的是:常规表单一般会提交带有name的按钮控件,而serialize()函数不会序列化带有name的按钮控件。更多详情请点击这里。

语法

jQuery 1.0 新增该函数。

jQueryObject.serialize( )

返回值

serialize()函数的返回值为String类型,返回将表单元素编码后的可用于表单提交的文本字符串。

请参考下面这段初始HTML代码:

<form name="myForm" action="http://www.365mini.com" method="post">
<input name="uid" type="hidden" value="1" />
<input name="username" type="text" value="张三" />
<input name="password" type="text" value="123456" />
<select name="grade" id="grade">
<option value="1">一年级</option>
<option value="2">二年级</option>
<option value="3" selected="selected">三年级</option>
<option value="4">四年级</option>
<option value="5">五年级</option>
<option value="6">六年级</option>
</select>
<input name="sex" type="radio" checked="checked" value="1" />男
<input name="sex" type="radio" value="0" />女
<input name="hobby" type="checkbox" checked="checked" value="1" />游泳
<input name="hobby" type="checkbox" checked="checked" value="2" />跑步
<input name="hobby" type="checkbox" value="3" />羽毛球
<input name="btn" id="btn" type="button" value="点击" />

对<form>元素进行序列化可以直接序列化其内部的所有表单元素。

// 序列化<form>内的所有表单元素
// 序列化后的结果:uid=1&username=%E5%BC%A0%E4%B8%89&password=123456&grade=3&sex=1&hobby=1&hobby=2
alert( $("form").serialize() );

我们也可以直接对部分表单元素进行序列化。

// 序列化所有的text、select、checkbox表单元素
// 序列化后的结果:username=%E5%BC%A0%E4%B8%89&password=123456&grade=3&hobby=1&hobby=2
alert( $(":text, select, :checkbox").serialize() );

serialize()函数通常用于将表单内容序列化,以便通过AJAX方式提交。

$("#btn").click( function(){

    // 将当前表单内容以POST请求的AJAX方式提交到"http://www.365mini.com"
$.post( "http://www.365mini.com", $("form").serialize(), function( data, textStatus, jqXHR ){
alert( "AJAX提交成功!" );
} ); } );

六、上传文件

form表单上传文件

html

<h3>form表单上传文件</h3>

<form action="/upload_file/" method="post" enctype="multipart/form-data">
<p><input type="file" name="upload_file_form"></p>
<input type="submit">
</form>

view

def index(request):

    return render(request,"index.html")

def upload_file(request):
print("FILES:",request.FILES)
print("POST:",request.POST)
return HttpResponse("上传成功!")

Ajax(FormData)

FormData是什么呢?

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".

比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.

所有主流浏览器的较新版本都已经支持这个对象了,比如Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。

html

<h3>Ajax上传文件</h3>

<p><input type="text" name="username" id="username" placeholder="username"></p>
<p><input type="file" name="upload_file_ajax" id="upload_file_ajax"></p> <button id="upload_button">提交</button>
{#注意button标签不要用在form表单中使用#} <script>
$("#upload_button").click(function(){ var username=$("#username").val();
var upload_file=$("#upload_file_ajax")[0].files[0]; var formData=new FormData();
formData.append("username",username);
formData.append("upload_file_ajax",upload_file); $.ajax({
url:"/upload_file/",
type:"POST",
data:formData,
contentType:false,
processData:false, success:function(){
alert("上传成功!")
}
}); })
</script>

views

def index(request):

    return render(request,"index.html")

def upload_file(request):
print("FILES:",request.FILES)
print("POST:",request.POST)
return HttpResponse("上传成功!")

伪造Ajax上传文件

iframe标签

<iframe> 标签规定一个内联框架。

一个内联框架被用来在当前 HTML 文档中嵌入另一个文档。

示例:

<iframe src="http://www.baidu.com" width="1000px" height="600px"></iframe>

iframe+form

<h3>伪造Ajax上传文件</h3>
<form action="/upload_file/" method="post" id="form2" target="ifr" enctype="multipart/form-data">
<p>
<iframe name="ifr" id="ifr"></iframe></p>
<p><input type="file" name="upload_file"></p>
<p><input type="text" name="user"></p> <input type="button" value="提交" id="submitBtn">
</form> <script> $("#submitBtn").click(function(){ $("#ifr").load(iframeLoaded);
$("#form2").submit(); }); function iframeLoaded(){
alert(123)
} </script>

views

def index(request):

    return render(request,"index.html")

def upload_file(request):
print("FILES:",request.FILES)
print("POST:",request.POST)
return HttpResponse("上传成功!")

七、同源策略与Jsonp

同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

示例:

项目1:

==================================http://127.0.0.1:8001项目的index
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body> <button>ajax</button>
{% csrf_token %} <script>
$("button").click(function(){ $.ajax({
url:"http://127.0.0.1:7766/SendAjax/",
type:"POST",
data:{"username":"yuan","csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()},
success:function(data){
alert(123);
alert(data)
}
})
})
</script>
</body>
</html> ==================================http://127.0.0.1:8001项目的views def index(request): return render(request,"index.html") def ajax(request):
import json
print(request.POST,"+++++++++++")
return HttpResponse(json.dumps("hello"))

项目2:

==================================http://127.0.0.1:8002项目的index
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body> <button>sendAjax</button> {% csrf_token %} <script>
$("button").click(function(){ $.ajax({
url:"/SendAjax/",
type:"POST",
data:{"username":"yuan","csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()},
success:function(data){
alert(data)
}
})
})
</script> </body>
</html> ==================================http://127.0.0.1:8002项目的views def index(request): return render(request,"index.html") from django.views.decorators.csrf import csrf_exempt @csrf_exempt def SendAjax(request): import json print("++++++++") return HttpResponse(json.dumps("hello2"))

当点击项目1的按钮时,发送了请求,但是会发现报错如下:

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:7766/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截。

Jsonp

jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

思考:这算怎么回事?

<script src="http://code.jquery.com/jquery-latest.js"></script>

借助script标签,实现跨域请求,示例:

# =============================http://127.0.0.1:8001/index

<button>ajax</button>
{% csrf_token %} <script>
function func(name){
alert(name)
}
</script> <script src="http://127.0.0.1:7766/SendAjax/"></script> # =============================http://127.0.0.1:8002/
from django.views.decorators.csrf import csrf_exempt @csrf_exempt def SendAjax(request): import json print("++++++++")
# dic={"k1":"v1"}
return HttpResponse("func('yuan')") # return HttpResponse("func('%s')"%json.dumps(dic))

这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。

一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。

<button onclick="f()">sendAjax</button>

<script>
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
document.body.removeChild(script);
} function func(name){
alert("hello"+name)
} function f(){
addScriptTag("http://127.0.0.1:7766/SendAjax/")
}
</script>

为了更加灵活,现在将你自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调:

将8001的f()改写为:

function f(){
addScriptTag("http://127.0.0.1:7766/SendAjax/?callbacks=func")
}

8002的views改为:

def SendAjax(request):

    import json

    dic={"k1":"v1"}

    print("callbacks:",request.GET.get("callbacks"))
callbacks=request.GET.get("callbacks") return HttpResponse("%s('%s')"%(callbacks,json.dumps(dic)))

jQuery对JSONP的实现

getJSON

jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法

8001的html改为:

<button onclick="f()">sendAjax</button>

<script>

    function f(){
$.getJSON("http://127.0.0.1:7766/SendAjax/?callbacks=?",function(arg){
alert("hello"+arg)
});
} </script>

8002的views不改动。

结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。

此外,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现

$.ajax

8001的html改为:

<script>

    function f(){
$.ajax({
url:"http://127.0.0.1:7766/SendAjax/",
dataType:"jsonp",
jsonp: 'callbacks',
jsonpCallback:"SayHi"
}); } function SayHi(arg){
alert(arg);
} </script>

8002的views不改动。

当然,最简单的形式还是通过回调函数来处理:

<script>

    function f(){

            $.ajax({
url:"http://127.0.0.1:7766/SendAjax/",
dataType:"jsonp", //必须有,告诉server,这次访问要的是一个jsonp的结果。
jsonp: 'callbacks', //jQuery帮助随机生成的:callbacks="wner"
success:function(data){
alert("hi "+data)
}
}); } </script>

jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',server端接受callback键对应值后就可以在其中填充数据打包返回了;

jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。  

注意 JSONP一定是GET请求

应用

<input type="button" onclick="AjaxRequest()" value="跨域Ajax" />

<div id="container"></div>

    <script type="text/javascript">
function AjaxRequest() {
$.ajax({
url: 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
type: 'GET',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'list',
success: function (data) { $.each(data.data,function(i){
var item = data.data[i];
var str = "<p>"+ item.week +"</p>";
$('#container').append(str);
$.each(item.list,function(j){
var temp = "<a href='" + item.list[j].link +"'>" + item.list[j].name +" </a><br/>";
$('#container').append(temp);
});
$('#container').append("<hr/>");
}) }
});
}
</script>

八、CORS

1、简介

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

2、两种请求

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同时满足上面两个条件,就属于非简单请求。

浏览器对这两种请求的处理,是不一样的。

Python学习(三十八)—— Djago之Ajax的更多相关文章

  1. python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制

    django  Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...

  2. Python学习(十八)—— 数据库(三)

    转载自http://www.cnblogs.com/linhaifeng/articles/7356064.html 一.数据操作 1.插入数据INSERT 1. 插入完整数据(顺序插入) 语法一: ...

  3. Python学习二十八周(vue.js)

    一.指令 1.一个例子简单实用vue: 下载vue.js(这里实用1.0.21版本) 编写html代码: <!DOCTYPE html> <html lang="en&qu ...

  4. Python学习日记(十八) 序列化模块

    什么是序列? 就是每一个元素被有序的排成一列 什么是序列化? 就是将原本的列表.字典等内容转化成字符串的过程 什么时候会用到序列化? 数据存储(把数据放在文件.数据库),网络传输等 序列化的目的 1. ...

  5. Python学习第十八篇——低耦合函数设计思想

    import json 2 def greet_user(filename): 3 try: 4 with open(filename) as f_obj: 5 username = json.loa ...

  6. python第三十八课——面向对象(一)

    1.面向对象:(思想) 面向:看.关注.瞅 对象:个体.实体.实例.结果单词:object在python中一些皆对象 面向过程:(思想) 面向:看.关注.瞅 过程:经过.经历.从头到尾 使用一些生活中 ...

  7. 笨办法学Python(三十八)

    习题 38: 阅读代码 现在去找一些 Python 代码阅读一下.你需要自己找代码,然后从中学习一些东西.你学到的东西已经足够让你看懂一些代码了,但你可能还无法理解这些代码的功能.这节课我要教给你的是 ...

  8. 前端学习(三十八)vue(笔记)

    Angular+Vue+React    Vue性能最好,Vue最轻=======================================================Angular     ...

  9. Python学习札记(十八) 高级特性4 生成器

    参考:生成器 Note 1.通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的,且容易造成空间浪费.所以,如果列表元素可以按照某种算法推算出来,那我们可以在循环的过程中 ...

  10. python学习三十九天filter() map()用法及lambda搭配使用

    python函数中的 filter() map() 前者是过滤的,后者是映射关系,需要与函数搭配使用,这时候匿名函数派上用场了,用简单的表达式就可以显示比较复杂的功能 1,python函数 filte ...

随机推荐

  1. BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)

    题面 求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\) 题解 首先考虑 dp ... 直接算可行的方案数 , 容易算重复 . 我们用总方案数减 ...

  2. LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)

    题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...

  3. AttributeError type object 'deprecated' has no attribute 'ROCKY'

    AttributeError type object 'deprecated' has no attribute 'ROCKY' 在使用kolla安装docker的时候遇到了AttributeErro ...

  4. Java【第三篇】基本语法之--选择结构

    Java分支语句分类 分支语句根据一定的条件有选择地执行或跳过特定的语句,分为两类: if-else 语句 switch 语句 if-else语句语法格式 if(布尔表达式){ 语句或语句块; } i ...

  5. Tensorflow基本语法

    一.tf.Variables() import tensorflow as tf Weights = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) se ...

  6. 老男孩Python全栈学习 S9 日常作业 007

    1.把列表中所有姓周的人的信息删掉 lst = ['周老二', '周星星', '麻花藤', '周扒皮'] lst = ['周老二', '周星星', '麻花藤', '周扒皮'] lst2 = [] fo ...

  7. jQuery使用(十三):工具方法

    proxy() onConflict() each() map() parseJson() makeArray() proxy() $.proxy()的实现机制与原生javaScript中的bind( ...

  8. java集合分割

    java集合分割成等份的小集合: private <T> List<List<T>> getSubList(List list,int len) { if(list ...

  9. [物理学与PDEs]第2章习题12 严格凸性的转换

    设 $L=L(\xi_0,\xi_1,\cdots,\xi_n)$ 关于变量 $\xi_0>0,\xi_1,\cdots,\xi_n$ 为严格凸的. 证明函数 $$\bex M=\cfrac{1 ...

  10. jpa返回List<Map<String, Object>>相当于jdbctemplate的queryForlist

    public class Test(){ @PersistenceContext(unitName = "manageFactory") protected EntityManag ...