Ajax准备知识:json

什么是json?

定义:

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

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

合格的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;} // 不能使用函数和日期对象
}  

stringify与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>

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>

view:

import json,time

def index(request):

    return render(request,"index.html")

def handle_Ajax(request):

    username=request.POST.get("username")
password=request.POST.get("password") print(username,password)
time.sleep(10) return HttpResponse(json.dumps("Error Data!"))

$.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跨站请求伪造

方式1

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

方式2

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

方式3:

<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

一、简介

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

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

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

二、两种请求

浏览器将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

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

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

* 简单请求和非简单请求的区别?

   简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检” - 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”rdquo;请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers

10 ajax的更多相关文章

  1. 一步步学习ASP.NET MVC3 (10)——@Ajax,JavaScriptResult(1)

    请注明转载地址:http://www.cnblogs.com/arhat 首先老魏先说一下抱歉,昨天由于在安装CentOS,Mono,Jexus配置Linux环境下的ASP.NET运行环境,花费了不少 ...

  2. js ajax php分页组件

    github  https://github.com/lihefen/pageList html页面 <!DOCTYPE html><html><head>< ...

  3. Ajax工作原理

    在写这篇文章之前,曾经写过一篇关于AJAX技术的随笔,不过涉及到的方面很窄,对AJAX技术的背景.原理.优缺点等各个方面都很少涉及null.这次写这篇文章的背景是因为公司需要对内部程序员做一个培训.项 ...

  4. 关于Ajax工作原理

    1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...

  5. url路由、模板语言、ajax、用django框架创建表

    1.后台管理的左侧菜单,默认只有第一个页签下面的选项是显示的,点了别的页签再显示别的页签下面的选项,问题是:点了任何菜单的选项后,左侧菜单又成了第一个页签的选项显示,别的页签隐藏,也就是左侧的菜单刷新 ...

  6. 原生ajax基础

    /*ajax对象的成员常用属性:responseText:以字符串形式接收服务器端返回的信息responseXML:以Xml Document对象形式接收服务器返回的信息readyState:返回当前 ...

  7. MVC5:使用Ajax和HTML5实现文件上传功能

    引言 在实际编程中,经常遇到实现文件上传并显示上传进度的功能,基于此目的,本文就为大家介绍不使用flash 或任何上传文件的插件来实现带有进度显示的文件上传功能. 基本功能:实现带有进度条的文件上传功 ...

  8. Ajax技术

    1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...

  9. Ajax工作原理(转)

    1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...

随机推荐

  1. TeamViewer安装使用

    1.下载安装包 官网下载最新安装包 2.安装步骤 3.连接 输入密码即可控制伙伴电脑.

  2. python模块详解 sys shutil

    sys模块 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sy ...

  3. http:origin,referer和host区别

    发起一个ajax请求时,request header里面有三个属性会涉及请求源信息.前端可能用不到这些值,但是,后台业务系统会比较关心它们,场景可能有: 处理跨域请求时,必须判断来源请求方是否合法:后 ...

  4. springboot项目搭建:结构和入门程序

    Spring Boot 推荐目录结构 代码层的结构 根目录:com.springboot 1.工程启动类(ApplicationServer.java)置于com.springboot.build包下 ...

  5. 使用ajax实现简单的带百分比进度条

    需求:当进行文件上传保存等操作时,能在页面显示一个带百分比的进度条,给用户一个好的交互体验 实现步骤 JSP页面 1.添加table标签 <table id="load" w ...

  6. Python中的Numpy、SciPy、MatPlotLib安装与配置

    Python安装完Numpy,SciPy和MatplotLib后,可以成为非常犀利的科研利器.网上关于这三个库的安装都写得非常不错,但是大部分人遇到的问题并不是如何安装,而是安装好后因为配置不当,在使 ...

  7. Wampserver由橙变绿的解决过程

    因为C盘的内存问题,就重装了win7系统,那么就面临着很对软件要重新进行安装,安装wampserver时,再次遇到了服务器的图标一直是橙色的而不变绿色,安装包地址: http://download.c ...

  8. .net core 操作域控 活动目录 ladp -- Support for System.DirectoryServices for Windows

    原文链接:https://github.com/dotnet/corefx/issues/2089 1. @ianhays to kick start the project in CoreFX re ...

  9. DOM笔记(十一):JavaScript对象的基本认识和创建

    一.什么是对象? 面 向对象(Object-Oriented,OO)的语言有一个标志,那就是都有类的概念,例如C++.Java等:但是ECMAScript没有类的概 念.ECMAScript-262把 ...

  10. robotframework实战一

    1.环境 1.Robotframework 安装环境,见以下帖子,只要保证python安装成功,安装了python的pip,就可以使用pip一路安装下去了.以下帖子也有基础的操作,帖子路径 http: ...