您当前的位置: 首页 >  Python

IT之一小佬

暂无认证

  • 0浏览

    0关注

    1192博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

python中flask_restful响应处理(marshal、marshal_with、fields、reqparse、representation)

IT之一小佬 发布时间:2021-08-10 21:07:39 ,浏览量:0

1 序列化数据

        Flask-RESTful 提供了marshal工具,用来帮助我们将数据序列化为特定格式的字典数据,以便作为视图的返回值。

from flask_restful import Resource, fields, marshal_with

resource_fields = {
    'name': fields.String,
    'address': fields.String,
    'user_id': fields.Integer
}

class Todo(Resource):
    @marshal_with(resource_fields, envelope='resource')
    def get(self, **kwargs):
        return db_get_todo()

也可以不使用装饰器的方式

class Todo(Resource):
    def get(self, **kwargs):
        data = db_get_todo()
        return marshal(data, resource_fields)

示例代码1:

from flask import Flask
from flask_restful import fields, Resource, marshal, marshal_with, Api

app = Flask(__name__)
api = Api(app)


# 用来模拟要返回的数据对象的类
class User(object):
    def __init__(self, user_id, name, age):
        self.user_id = user_id
        self.name = name
        self.age = age


resoure_fields = {
    'user_id': fields.Integer,
    'name': fields.String
}


class Demo1Resource(Resource):
    @marshal_with(resoure_fields, envelope='data1')
    def get(self):
        user = User(1, 'itcast', 12)
        return user


class Demo2Resource(Resource):
    def get(self):
        user = User(1, 'itcast', 12)
        return marshal(user, resoure_fields, envelope='data2')


# api.add_resource(Demo1Resource, '/demo1')
api.add_resource(Demo2Resource, '/demo2')

app.run()

运行效果:

 

 测试代码2:

 

示例代码3:

from flask import Flask
from flask_restful import reqparse, Api, Resource, fields, marshal_with

app = Flask(__name__)
api = Api(app)

# 1. 关于参数解析的部分
# 一组虚拟的数据
TODOS = {
    'todo1': {'task': 1},
    'todo2': {'task': 2},
    'todo3': {'task': 3},
}

# 定义允许的参数为task,类型为int,以及错误时的提示
parser = reqparse.RequestParser()
parser.add_argument('task', type=int, help='Please set a int task content!')


# 真正处理请求的地方
class TodoList(Resource):
    def get(self):
        return TODOS, 200, {'Etag': 'some-opaque-string'}

    def post(self):
        args = parser.parse_args()
        print(max(TODOS.keys()), type(max(TODOS.keys())))
        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
        todo_id = 'todo%i' % todo_id
        TODOS[todo_id] = {'task': args['task']}
        return TODOS[todo_id], 201


# 实际定义路由的地方
api.add_resource(TodoList, '/todos', '/all_tasks')


# 2. 关于响应域的部分
# ORM的数据模型
class TodoDao(object):
    def __init__(self, todo_id, task):
        self.todo_id = todo_id
        self.task = task

        # 这个域不会被返回
        self.status = 'active'


# marshal-蒙板,
resource_fields = {
    'task': fields.String,
    'url': fields.Url('todo_ep')
}


# 真正处理请求的地方
class Todo(Resource):
    # 蒙板 把多余的参数蒙住,只返回resource_fields中声明的键值对
    @marshal_with(resource_fields)
    def get(self, todo_id):
        return TodoDao(todo_id=todo_id, task='Remember the milk'), 200


# 实际定义路由的地方
api.add_resource(Todo, '/todos/', endpoint='todo_ep')  # 类Todo中只写了get方法

if __name__ == '__main__':
    app.run(debug=True)

运行结果:

get功能:

 post功能:

 

2 定制返回的JSON格式 需求

想要接口返回的JSON数据具有如下统一的格式

{"message": "描述信息", "data": {要返回的具体数据}}

在接口处理正常的情况下, message返回ok即可,但是若想每个接口正确返回时省略message字段

class DemoResource(Resource):
    def get(self):
        return {'user_id':1, 'name': 'itcast'}

对于诸如此类的接口,能否在某处统一格式化成上述需求格式?

{"message": "OK", "data": {'user_id':1, 'name': 'itcast'}}
解决

Flask-RESTful的Api对象提供了一个representation的装饰器,允许定制返回数据的呈现格式

api = Api(app)

@api.representation('application/json')
def handle_json(data, code, headers):
    # TODO 此处添加自定义处理
    return resp

Flask-RESTful原始对于json的格式处理方式如下:

代码出处:flask_restful.representations.json

from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps


def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    settings = current_app.config.get('RESTFUL_JSON', {})

    # If we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here.  Note that this won't override any existing value
    # that was set.  We also set the "sort_keys" value.
    if current_app.debug:
        settings.setdefault('indent', 4)
        settings.setdefault('sort_keys', not PY3)

    # always end the json dumps with a new line
    # see https://github.com/mitsuhiko/flask/pull/1262
    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp

为满足需求,做如下改动即可

@api.representation('application/json')
def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    # 此处为自己添加***************
    if 'message' not in data:
        data = {
            'message': 'OK',
            'data': data
        }
    # **************************

    settings = current_app.config.get('RESTFUL_JSON', {})

    # If we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here.  Note that this won't override any existing value
    # that was set.  We also set the "sort_keys" value.
    if current_app.debug:
        settings.setdefault('indent', 4)
        settings.setdefault('sort_keys', not PY3)

    # always end the json dumps with a new line
    # see https://github.com/mitsuhiko/flask/pull/1262
    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp
关注
打赏
1665675218
查看更多评论
立即登录/注册

微信扫码登录

0.0412s