Flask 学习-75.Flask-RESTX 使用 marshal_with 处理嵌套字段

Posted 上海-悠悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask 学习-75.Flask-RESTX 使用 marshal_with 处理嵌套字段相关的知识,希望对你有一定的参考价值。

前言

使用 marshal_with 序列化模型非常方便,还可以处理一些嵌套字段。

嵌套字段

虽然使用 dicts 嵌套字段可以将平面数据对象转换为嵌套响应,但您可以使用它 Nested 来解组嵌套数据结构并适当地呈现它们。

官方文档示例

>>> from flask_restx import fields, marshal
>>> import json
>>>
>>> address_fields = 
>>> address_fields['line 1'] = fields.String(attribute='addr1')
>>> address_fields['line 2'] = fields.String(attribute='addr2')
>>> address_fields['city'] = fields.String(attribute='city')
>>> address_fields['state'] = fields.String(attribute='state')
>>> address_fields['zip'] = fields.String(attribute='zip')
>>>
>>> resource_fields = 
>>> resource_fields['name'] = fields.String
>>> resource_fields['billing_address'] = fields.Nested(address_fields)
>>> resource_fields['shipping_address'] = fields.Nested(address_fields)
>>> address1 = 'addr1': '123 fake street', 'city': 'New York', 'state': 'NY', 'zip': '10468'
>>> address2 = 'addr1': '555 nowhere', 'city': 'New York', 'state': 'NY', 'zip': '10468'
>>> data = 'name': 'bob', 'billing_address': address1, 'shipping_address': address2
>>>
>>> json.dumps(marshal(data, resource_fields))
'"billing_address": "line 1": "123 fake street", "line 2": null, "state": "NY", "zip": "10468", "city": "New York", 
"name": "bob", "shipping_address": "line 1": "555 nowhere", "line 2": null, "state": "NY", "zip": "10468", "city": "New York"'

此示例使用两个Nested字段。构造Nested函数需要一个字段字典来呈现为 sub-fields.input。构造函数和嵌套字典(上一个示例)之间的重要区别在于Nested属性的上下文。
在此示例中, billing_address是一个具有自己的字段的复杂对象,并且传递给嵌套字段的上下文是子对象而不是原始data对象。
换句话说: data.billing_address.addr1在这里是在范围内,而在前面的例子data.addr1中是位置属性。记住:对象Nested为List属性创建了一个新的范围。

默认情况下,当子对象为None时,将生成具有嵌套字段默认值的对象,而不是null。这可以通过传递allow_null参数来修改,Nested有关更多详细信息,请参阅构造函数。
使用NestedwithList来编组更复杂对象的列表:

user_fields = api.model('User', 
    'id': fields.Integer,
    'name': fields.String,
)

user_list_fields = api.model('UserList', 
    'users': fields.List(fields.Nested(user_fields)),
)

使用示例

比如我们想返回以下格式, data 是查询的对象序列化后的json


    "code": 0,
    "msg": "success",
    "data": 
        "id": 1
        ......
    

使用 fields.Nested 嵌套字段

teacher_model = api.model('TeacherModel', 
    'name': fields.String(
        max_length=50, required=True, description='姓名'),
    'size': fields.String(
        enum=["SMALL", "MEDIUM", "LARGE"], required=False, description='型号'),
    'address': fields.String(max_length=150, description='邮箱')
)


new_fields = 
new_fields['code'] = fields.Integer(default=0)
new_fields['message'] = fields.String(default='success')
new_fields['data'] = fields.Nested(teacher_model)

在返回的时候,就不能直接返回模型了,需按new_fields结构返回

@api.route('/teacher')
class TeacherView(Resource):

    @api.doc(description='新增老师')
    @api.marshal_with(new_fields)
    @api.expect(teacher_model, validate=True)
    def post(self):
        """
            add teacher
        """
        api.logger.info(f"获取请求参数: api.payload")
        t = Teachers(
                name=api.payload.get('name'),
                size=api.payload.get('size'),
                address=api.payload.get('address'),
            )
        t.save()  # 保存数据
        return "data": t, HTTPStatus.CREATED

测试接口

POST http://127.0.0.1:5000/api/v1/teacher HTTP/1.1
User-Agent: Fiddler
Host: 127.0.0.1:5000
Content-Length: 18
Content-Type: application/json

"name": "yoyo"

HTTP/1.0 201 CREATED
Content-Type: application/json
Content-Length: 141
Server: Werkzeug/2.0.2 Python/3.8.5
Date: Fri, 23 Sep 2022 02:03:31 GMT


    "code": 0,
    "message": "success",
    "data": 
        "name": "yoyo",
        "size": "MEDIUM",
        "address": null
    

以上是关于Flask 学习-75.Flask-RESTX 使用 marshal_with 处理嵌套字段的主要内容,如果未能解决你的问题,请参考以下文章

Flask 与 Django 先学哪个呢

Python/Flask - 使“/index”重定向到“/”

个人技术总结——flask-socketio框架

如何使 Flask-WTForms 从标签名称列表中动态更新标签?

试图在 Flask-SQLAlchemy 中使查询不区分大小写 [重复]

flask如何使模板返回大文件,又不消耗大量内存