目录
day09回顾
1.前后端处理JSON
- 后端处理
import json
json.dumps(列表|元组|字典)
class Model(db.Model):
...
def to_dict(self):
dic = {
...
}
return dic - 前端处理
var jsonObj = JSON.parse(JSON串)
2.JQ 对 ajax 支持
- $obj.load()
语法:$obj.load(url,data,callback) - $.get()
语法:$.get(url,data,callback,type)
$.get('/01-server',function(data){
data就是JSON格式
},'json') - $.port()
1.JQ 对 ajax的支持
- $.ajax()
语法:$.ajax({请求参数的JSON对象});
参数对象中的属性:- url:字符串,表示异步请求的地址
- type:字符串,请求方式,get 或 post
- data:传递到服务器端的参数
可以是字符串 :‘name=sf.zh&age=18’
也可以是JSON对象:
{
'name':'sf.zh',
'age':18
} - dataType:字符串,响应回来的数据的格式
- ‘html’
- 'xml'
- 'text'
- 'script'
- 'json'
- 'jsonp':有关跨域的响应格式
- success:回调函数,请求和响应成功时回来执行的操作
--------------------------------------------------------------------------- - error:回调函数,请求或响应失败时回来执行的操作
- beforeSend:回调函数,发送ajax请求之前执行的操作,如果是return false,则终止请求发送
2.跨域(Cross Domain)
- 什么是跨域
HTTP协议中有一个策略 - ‘同源策略’
同源:多个地址中,相同协议,相同域名,相同端口被视为是‘同源’
在HTTP中,必须是同源地址才能互相发送请求,非同源拒绝请求(<script>和<img>除外)。
http://www.tedu.cn/a.html
http://www.tedu.cn/b.html
以上地址是同源
https://www.tedu.cn/a.html
http://www.tedu.cn/b.html
由于协议不同,所以不是‘同源’
http://localhost/a.html
http://127.0.0.1/a.html
由于域名不同,所以不是‘同源’
http://www.tedu.cn:80/a.html
http://www.tedu.cn:8000/b.html
由于端口不同,所以不是‘同源’
跨域:非同源的网页,相互发送请求的过程,就是跨域 - 解决方案
通过<script> 向服务器资源发送请求
由服务器资源指定前端页面的哪个方法来执行响应的数据
示例06-crossdomain.html / 07-flight.html - jquery 的跨域
$.ajax({
url:'xxx',
type:'get',
dataType:'jsonp', //指定为跨域访问
jsonp:'callback', //定义了callback的参数名,以便获取callback传递过去的函数名
jsonpCallback:'xxx' //定义jsonp的回调函数名
});
今日示例:
AjaxDemo2.py
from flask import Flask, render_template, request
import json
from flask_sqlalchemy import SQLAlchemy
import pymysql
pymysql.install_as_MySQLdb()
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']="mysql://root:123456@localhost:3306/flask"
db = SQLAlchemy(app)
class Users(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer,primary_key=True)
uname = db.Column(db.String(50))
upwd = db.Column(db.String(50))
realname = db.Column(db.String(30))
# 将当前对象中的所有属性封装到一个字典中
def to_dict(self):
dic = {
'id':self.id,
'uname':self.uname,
'upwd':self.upwd,
'realname':self.realname
}
return dic
def __repr__(self):
return "<Users:%r>" % self.uname
class Province(db.Model):
__tablename__ = "province"
id = db.Column(db.Integer,primary_key=True)
proname = db.Column(db.String(30),nullable=False)
cities = db.relationship('City',backref='province',lazy='dynamic')
def to_dict(self):
dic = {
'id' : self.id,
'proname':self.proname
}
return dic
def __init__(self,proname):
self.proname = proname
def __repr__(self):
return "<Province:%r>" % self.proname
class City(db.Model):
__tablename__ = "city"
id = db.Column(db.Integer,primary_key=True)
cityname = db.Column(db.String(30),nullable=False)
pro_id = db.Column(db.Integer,db.ForeignKey("province.id"))
def to_dict(self):
dic = {
'id' : self.id,
'cityname' : self.cityname,
'pro_id' : self.pro_id,
}
return dic
def __init__(self,cityname,pro_id):
self.cityname = cityname
self.pro_id = pro_id
def __repr__(self):
return "<City:%r>" % self.cityname
db.create_all()
@app.route('/02-province')
def province_views():
return render_template('02-province.html')
@app.route('/02-loadPro')
def loadPro_views():
provinces = Province.query.all()
list = []
for pro in provinces:
list.append(pro.to_dict())
return json.dumps(list)
@app.route('/02-loadCity')
def loadCity_views():
# 接收前端传递过来的数据,pid为前端传递过来的参数名
pid = request.args.get('pid')
cities = City.query.filter_by(pro_id=pid).all()
list = []
for city in cities:
list.append(city.to_dict())
return json.dumps(list)
######### 2018.10.09########
@app.route("/05-server")
def server_05():
uname = request.args.get('uname')
u = Users.query.filter_by(uname=uname).first()
if u :
return json.dumps(u.to_dict())
else:
dic = {
'status' : "0",
'msg' : '查找的用户不存在'
}
return json.dumps(dic)
@app.route('/06-server')
def server_06():
# 接收前端传递过来的callback即前端处理响应数据的函数名
cb = request.args.get('callback')
#响应数据,被前端页面当成JS脚本被执行
return cb+"('这是server_06响应回来的数据')"
@app.route('/07-server')
def server_07():
cb = request.args.get('callback')
dic = {
'flightNO':'MU763',
'from':'Beijing',
'to':'Saipan',
'time':'16:55'
}
# flight({'flightNO':'MU763'...})
return cb+"("+json.dumps(dic)+")"
if __name__ == '__main__':
app.run(debug=True)
02-province.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/js/common.js"></script>
<script src="/static/js/jquery-1.11.3.js"></script>
<script>
function loadPro(){
/*var xhr = createXhr();
//false : 表示采用同步的方式执行,必须保证loadPro()执完毕之后才能执行其他的操作
xhr.open('get','/02-loadPro',false);
xhr.onreadystatechange = function(){
if(xhr.readyState==4 && xhr.status==200){
var arr = JSON.parse(xhr.responseText);
var html = "";
$.each(arr,function(i,obj){
html += "<option value='"+obj.id+"'>";
html += obj.proname;
html += "</option>";
});
$("#selPro").html(html);
}
}
xhr.send(null);*/
//使用 $.ajax()
$.ajax({
url:'/02-loadPro',
type:'get',
dataType:'json',
async:false, //异步
success:function(data){
var html="";
$.each(data,function(i,obj){
html += "<option value='"+obj.id+"'>";
html += obj.proname;
html += "</option>";
});
$("#selPro").html(html);
}
});
}
/**
* 根据省份的id查询对应的所有的城市信息
* 参数pid:要查询的省份的id
* */
function loadCity(pid){
/*var xhr = createXhr();
var url = '/02-loadCity?pid='+pid;
xhr.open('get',url,true);
xhr.onreadystatechange = function(){
if(xhr.readyState==4&&xhr.status == 200){
var arr = JSON.parse(xhr.responseText);
var html = "";
$.each(arr,function(i,obj){
html+="<option value='"+obj.id+"'>";
html+=obj.cityname;
html+="</option>";
});
$("#selCity").html(html);
}
}
xhr.send(null);*/
//使用$.get()
$.get(
"/02-loadCity",
{'pid':pid},
function(data){
var html = "";
$.each(data,function(i,obj){
html+="<option value='"+obj.id+"'>";
html+=obj.cityname;
html+="</option>";
});
$("#selCity").html(html);
},'json');
}
$(function(){
/**加载所有的省份信息*/
loadPro();
/**为selPro绑定change事件*/
$("#selPro").change(function(){
loadCity(this.value);
});
/**调用loadCity(),先将默认的城市加载进来*/
console.log($("#selPro").val());
loadCity($("#selPro").val());
});
</script>
</head>
<body>
<select id="selPro">
</select>
<select id="selCity"></select>
</body>
</html>
05-ajax.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/jquery-1.11.3.js"></script>
</head>
<body>
{% if uname %}
{{ uname }}
{% endif %}
<h1>这是静态网页</h1>
<p>
用户名:<input type="text" id="uname">
</p>
<button id="btnAjax">ajax查询</button>
<p id="show"></p>
<script>
$(function(){
$("#btnAjax").click(function(){
//使用get请求方式,发送参数名为uname的数据到服务器
$.ajax({
//请求地址
url:'/05-server',
//请求方式
type:'get',
//请求参数
data:"uname="+$("#uname").val(),
//响应回来的数据格式
dataType:'json',
//请求和响应成功之后的回调函数
success:function(data){
var html="";
if(data.id){
//如果data中有id属性,则说明查询成功
html+="<h3>id:"+data.id+"</h3>";
html+="<h3>username:"+data.uname+"</h3>";
html+="<h3>age:"+data.upwd+"</h3>";
html+="<h3>email:"+data.realname+"</h3>";
}else{
//data中没有id属性,说明查询失败
html+="<h3>"+data.msg+"</h3>";
html+="<h3>"+data.status+"</h3>"
}
$("#show").html(html);
}
});
}) ;
});
</script>
</body>
</html>
06-crossdomain.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域</title>
<script src="js/jquery-1.11.3.js"></script>
</head>
<body>
<button id="btn">跨域请求</button>
<div id="show"></div>
<script>
/**
* 跨域调用的方法,由服务器端来指定调用
* */
function print(data){
console.log("服务器端传递的数据:"+data);
}
$(function(){
$("#btn").click(function(){
//正常的ajax请求无法完成跨域访问
/*var url = "http://127.0.0.1:5000/06-server"
$.get(url,function(data){
$("#show").html(data);
});*/
//原生的js完成跨域请求
//获取页面上的body标签
var body = document.getElementsByTagName("body")[0];
//动态的创建一对script标记,来完成js的请求,
//通过<script>产生的请求,响应回来的数据一律当成js脚本被执行
var script = document.createElement("script");
//为script标记的type属性赋值
script.type = "text/javascript"
//指定script标记的请求地址,callback参数表示告诉后端前端处理响应数据的函数名
script.src = "http://127.0.0.1:5000/06-server?callback=print";
//将script标记追加到当前页面:也就是向src的地址发送请求,同时接收响应数据,响应数据直接交给了页面,由页面当成js的脚本去执行
body.append(script);
//return "show('这是server_06响应回来的数据')"
});
});
</script>
</body>
</html>
07-flight.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/jquery-1.11.3.js"></script>
</head>
<body>
<button id="btnShow">显示</button>
<div id="show"></div>
<script>
function flight(data){
html = "";
html += "<h3>航班号:"+data.flightNO+"</h3>";
html += "<h3>出发:"+data.from+"</h3>";
html += "<h3>到达:"+data.to+"</h3>";
html += "<h3>时间:"+data.time+"</h3>";
$("#show").html(html);
}
$(function(){
$("#btnShow").click(function(){
//原生的跨域请求
/*var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.type = "text/javascript"
script.src = "http://127.0.0.1:5000/07-server?callback=flight";
body.append(script);*/
//jquery跨域请求 - jsonp
/*$.ajax({
url : 'http://127.0.0.1:5000/07-server',
type : 'get',
dataType : "jsonp",
jsonp:'callback',
jsonpCallback:'flight'
});*/
//jquery 跨域请求 - jsonp (简易版)
$.ajax({
url : 'http://127.0.0.1:5000/07-server',
type : 'get',
dataType : 'jsonp',
success:function(data){
console.log("航班:"+data.flightNO);
console.log("出发:"+data.from);
console.log("到达:"+data.to);
console.log("时间:"+data.time);
}
});
});
});
</script>
</body>
</html>