最近有点忙,flask开始用于生产中了,在这个json为主的微服务架构的天下,flask确实很得心应手。
下面总结一下最近的实践吧,分几个部分来写。
1、ajax发送和接收flask的json和值
2、flask接收ajax的json和值
3、flask返回json和值
下面开始:
1、ajax发送和接收flask的json和值
最方便就是用jquery了。之前试过用原生的方法,都是有的问题,特别是jsonp,更是麻烦。
所以,乖乖用jquery吧。
引用jquery很简单嘛,<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
//get传值,获取jsonp
$.ajax({
url: "http://127.0.0.1:5000/main/get_json/999",
dataType: "jsonp",
jsonp: "callback",
success: function (data) {
alert(data.hits);
}
})
这个是用jqery的ajax最原生的方式,最大的好处就是可以设置超时后的回调事件,这里没写出来。
这个是获取jsonp的方式,如果是获得json,也是一样的,更简单,去掉相应的dataType和jsonp就行了。
data是返回的json,取值的话就取相应的字段,hits这样的。
post传递json,返回获取json
//post传递json,返回获取json
//创建传递的参数
var postdata = {
ID: 1
};
$.post("http://127.0.0.1:5000/main/post_json/", postdata, function (data) {
if (data.ret == "OK") {
alert("成功!");
}
else {
alert("失败,原因:" + data.ret);
}
}
ajax基本上有很多资料了,都不难。下面是重点,flask方的。
2、flask接收ajax的json和值
接收get的值我实践过了,很简单,也就是一般的request.args.get。
接收post过来的json没试过,看资料是这样的
@app.route('/json', methods=['POST'])
def my_json():
print request.headers
print request.json
rt = {'info':'hello '+request.json['name']}
return Response(json.dumps(rt), mimetype='application/json')
3、flask返回json和值
先说简单的,返回一个值。
就直接return一个str回去就行了。
比如
return "100"
return str(100)
下面是最复杂的了,返回json。
A、直接返回json
这个也简单
from flask import jsonify
#返回单值
@app.route('/get_count/<unique_mark>')
def get_count(unique_mark):
return jsonify(hits=0)
#返回list
@app.route('/get_count/<unique_mark>')
def get_count(unique_mark):
ret=[1,2,3,4,5]
return jsonify(ret_list=ret)
这2个是基本的用法,但是对于大部分人来说,最大的问题是怎么返回一个flask-sqlalchemy的查询结果集。
这个我研究了很久,终于折腾出了一个class,只要继承之,就搞定鸟!
下面放出那个class。
class AutoSerialize(object):
'''
Mixin for retrieving public fields of model in json-compatible format
'''
__allowed_in_json__ = None
def get_serialize(self, exclude=()):
'''Returns model's PUBLIC data for jsonify'''
data = {}
keys = self._sa_class_manager.mapper.mapped_table.columns
public = self.__allowed_in_json__
for col in keys:
if public is not None:
if col.name not in public:
continue
if col.name in exclude:
continue
data[col.name] = self._serialize(getattr(self, col.name))
return data
@classmethod
def _serialize(cls, value):
if type(value) in (int, float, long, bool):
ret = str(value)
elif type(value) is unicode:
ret = value.encode('utf-8')
elif isinstance(value, datetime.date):
ret = value.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(value, datetime.time) or isinstance(value, datetime.datetime):
ret = value.isoformat()
elif isinstance(value, decimal.Decimal):
ret = str(value)
else:
ret = value
return ret
这个class的作用其实很简单,就是序列化一个结果集。
用法是这样:
先是一个普通的model类,继承一下它:
class User(db.Model, AutoSerialize):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25), default='')
mobile = db.Column(db.String(20), default='')
prize = db.Column(db.Integer, default=0)
create_time = db.Column(db.DateTime)
upload = db.Column(db.String(25), default='')
在就是查询出来后,要这样讲结果集转换成列表。
@bp.route('/get_prize_users/')
def get_prize_users():
page_index = int(request.args.get('page')) or 1
page_size = int(request.args.get('rows')) or 20
users_count = User.query.filter_by(prize=1).count()
users = User.query.filter_by(prize=1).order_by(User.id.desc()).paginate(page_index, page_size, False)
return jsonify(total=users_count, rows=[u.get_serialize() for u in users.items])
重点就在这里:
rows=[u.get_serialize() for u in users.items]
话说,python写着就是爽啊那么一句话就搞定别的语言一堆的代码。
另外说一下,上面那个get_prize_users()返回的结果集,是用在easyui里的datagrid上的。
最后的一关,jsonp。
其实jsonp不神秘,但是从前面可以知道,要在ajax里用callback来调用。
所以,普通的json只要包装一下,就是jsonp了。其实包装是比较麻烦的,但是python就是牛啊,我们做一个修饰器搞定。
def support_jsonp(f):
"""Wraps JSONified output for JSONP"""
@wraps(f)
def decorated_function(*args, **kwargs):
callback = request.args.get('callback', False)
if callback:
content = str(callback) + '(' + str(f(*args, **kwargs).data) + ')'
return current_app.response_class(content, mimetype='application/javascript')
else:
return f(*args, **kwargs)
return decorated_function
就是上面那货了,怎么用哈哈,修饰器嘛,和我们最常用的@app.route没区别。
@bp.route('/get_count/<unique_mark>')
@support_jsonp
def get_count(unique_mark):
link = Link.get_id_by_unique_mark(unique_mark)
if link is None:
return jsonify(hits=0)
else:
return jsonify(hits=link.hits)
就是那么简单!
fin.