在Flask API中将嵌套字段展平为数组

时间:2020-02-22 11:04:38

标签: python flask marshmallow flask-restplus

我正在使用flask_restplus构建API。

我有两个模型:

model_barcode = api.model('Barcode', {
        'code': fields.String,
    })

model_product = api.model('Product', {
        'id': fields.Integer,
        'name': fields.String,
        'barcodes': fields.Nested(model_barcode, as_list=True),
    })

ProductBarcode之间的关系是多对多的。

API响应如下:

[
    {
        "id": 15707,
        "name": "Jojo Leaf Eater - White",
        "barcodes": [
            {
                "code": "6009702666853"
            },
            {
                "code": "9317118010229"
            },
            {
                "code": "6009194082315"
            },
            {
                "code": "6009149569649"
            }
        ]
    }
]

但是,由于条形码模型的内容只是一个字段,所以我希望它像这样封送:

[
    {
        "id": 15707,
        "name": "Jojo Leaf Eater - White",
        "barcodes": ["6009702666853", "9317118010229",
                     "6009194082315", "6009149569649"]
    }
]

我该怎么做?

我尝试将对fields.Nested()的调用包装到fields.List()中,但这没有帮助。

如果有人对如何完成这项工作有任何想法,我将非常感谢您的帮助!

谢谢。

背景信息

以下是相关的软件包版本:

Flask==1.1.1
flask-restplus==0.13.0
marshmallow==3.3.0
SQLAlchemy==1.3.11
simplejson==3.17.0

数据库类

以下是SQLAlchemy类的定义:

class Product(Base):
    __tablename__ = 'product'

    id                  = Column(Integer, primary_key=True)
    name                = Column(String(256))
    barcodes            = relationship('Barcode',
                                       secondary='product_barcode',
                                       back_populates='products')

class Barcode(Base):
    __tablename__ = 'barcode'

    id                  = Column(Integer, primary_key=True)
    code                = Column(String(15))
    products            = relationship('Product',
                                       secondary='product_barcode',
                                       back_populates='barcodes')

替代实施

我有一个使用棉花糖的有效实现方式。

from marshmallow import Schema, fields

class BarcodeSchema(Schema):
    class Meta:
        fields = ('id', 'code',)

class ProductDetailSchema(Schema):
    barcodes = fields.Pluck(BarcodeSchema, "code", many=True)
    class Meta:
        fields = ('id', 'name', 'barcodes')
        ordered = False

这正是我想要的。但是,我真的更喜欢使用flask_restplus模型,因为它们使实际API的代码更加整洁。

1 个答案:

答案 0 :(得分:0)

您可以像这样轻松完成

'barcodes': fields.List(fields.String, attribute=lambda p: [product.code for product in p.barcodes])