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>姓名  <input class="v1" type="text" name="username" mark="用户名"></p><p>密码  <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 | errorconsole.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,timedef 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 jsondef 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)    #字典的键直接转成字符串namepwdreturn 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><br><br><br>$.ajax({<br>...<br>data:{
"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val();
}<br>})

方式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) {// 适用于IE6try {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的1234,四种状态时被调用;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_exemptdef 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_exemptdef 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)。

该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在标签内的表单控件不会被提交、没有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>内的所有表单元素
// 序列化后的结果: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标签

标签规定一个内联框架。

一个内联框架被用来在当前 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项目的viewsdef index(request):return render(request,"index.html")def ajax(request):import jsonprint(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项目的viewsdef index(request):return render(request,"index.html")from django.views.decorators.csrf import csrf_exempt@csrf_exemptdef SendAjax(request):import jsonprint("++++++++")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_exemptdef SendAjax(request):import jsonprint("++++++++")# 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 jsondic={"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
“预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers

Django开发学习之Ajax(二)相关推荐

  1. Windows驱动开发学习笔记(二)—— 驱动调试内核编程基础

    Windows驱动开发学习笔记(二)-- 驱动调试&内核编程基础 基础知识 驱动调试 PDB(Program Debug Database) WinDbg 加载 PDB 实验:调试 .sys ...

  2. c# AE GIS二次开发学习专题(二) 基本地图控件使用

    GIS二次开发学习专题(二) 基本地图控件使用 学习资料来自<牟乃夏 AE开发教程-基于C#.NET> 发的代码是我整理+老师布置的作业 这一部分是地图基本控件的使用与编写,包括: 一.二 ...

  3. Polyworks脚本开发学习笔记(十二)-输出和读取文本文件

    Polyworks脚本开发学习笔记(十二)-输出和读取文本文件 Polyworks作为一个测量工具,将测量的数据方便的导出到文本文件则是一项必须的功能.在DATA_FILE这个命令下提供了很多子命令用 ...

  4. Linux——Django 开发环境部署(二)python版本控制器pyenv

    python版本控制器pyenv 之前的 那篇是说明了django环境的site package完全独立出来了,但是使用的python解释器还是系统的,为了继续独立出来,甚至是达到ruby的rvm的自 ...

  5. Linux开发学习笔记(二)

    (温馨提示:内容有点多,可点右边的目录进行跳转) Shell编程 1.简单介绍 Shell 脚本(shell script),是一种为 shell 编写的脚本程序.Shell 编程跟 java.php ...

  6. 前端开发学习笔记(二)JavaScript DOM编程技术(一、二)

    陆陆续续看了将近2周的时间,其实书中的内容不难理解,只不过最近的事情较多,不能静下心来. 第一章 JavaScript简史 采用标准化的思路来建立网站,引入"WEB标准"技术.XH ...

  7. Django开发学习之Django-MTV

    MTV模型 Django的MTV分别代表: Model(模型):负责业务对象与数据库的对象(ORM)Template(模版):负责如何把页面展示给用户View(视图):负责业务逻辑,并在适当的时候调用 ...

  8. GTK+图形化应用程序开发学习笔记(二)—Glib库

    在学习GTK+之前我们需要先学习一下 glib的有关知识.因为我们将会在以后的学习中遇到这些知识.由于本笔记不是专门介绍glib的,所以下面的介绍不会太详细.   一.什么是glib库        ...

  9. 小程序云开发学习笔记(二)

    目录 JavaScript入门 操作数组 分隔符join方法 数组push方法 移除最后一项pop方法 操作对象 给已有对象添加属性和值 删除对象的某个属性 常量 字符串的操作 Math对象 Date ...

最新文章

  1. Awk 实战详解教程
  2. Swift学习之map、flatMap、filter、reduce的使用
  3. ubuntu下主目录的路径是什么
  4. rabbin负载均衡
  5. 各主流浏览器内核介绍
  6. Linux CentOs6 命令学习
  7. 分布式压测系列之Jmeter4.0
  8. Unity3D AssetBundle相关
  9. 【重点】LeetCode 146. LRU Cache
  10. Jquery 中each循环嵌套的使用示例教程
  11. 客户端调用服务器端方法——ASP.NET AJAX(Atlas)、Anthem.NET和Ajax.NET Professional实现之小小比较[转]...
  12. SDK Manager配置
  13. 为qt程序添加ico图标
  14. 2022年iOS面试题简答题
  15. 为什么很多开发都要转测试....详谈....
  16. LED背光源和LED背光灯区别
  17. 微信自动回复如何实现?用 Python 就可以
  18. 服务窗口关闭了,服务就停止了,真特么烦 pm2了解一下
  19. 用Enterprise Architect画类图和顺序图(一)
  20. 《云计算和大数据时代网络技术揭秘》读后感

热门文章

  1. BATH围猎新基建,后浪“TMD”集体缺席
  2. OpenGL显示窗口重定形函数
  3. myeclipse下用axis2开发web service
  4. 安装VirtualBox和导入虚拟电脑出现的问题
  5. Python:统计大小写字母个数和数字个数
  6. 利用CSV 引擎加载数据
  7. C++智能指针详解(auto_ptr、unique_ptr、shared_ptr)
  8. 盐城北大青鸟植树节丨迎接春天,种下美好
  9. WireShark黑客发现之旅(7)—勒索邮件
  10. TS流解析 ffmpeg