总结一下flask和ajax之间的json、jsonp通讯

最近有点忙,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.

转载于:https://my.oschina.net/klausgao/blog/359237

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值