Description
I asked this question on StackOverflow (here) but didn't get any help there. I'm sure that there is a simple answer to this.
I'm using flask_restplus
to build an API.
I have two models:
model_barcode = api.model('Barcode', {
'code': fields.String,
})
and
model_product = api.model('Product', {
'id': fields.Integer,
'name': fields.String,
'barcodes': fields.Nested(model_barcode, as_list=True),
})
The relationship between Product
and Barcode
is many-to-many.
The API response looks like this:
[
{
"id": 15707,
"name": "Jojo Leaf Eater - White",
"barcodes": [
{
"code": "6009702666853"
},
{
"code": "9317118010229"
},
{
"code": "6009194082315"
},
{
"code": "6009149569649"
}
]
}
]
However, since the contents of the barcode model are just a single field I want it to marshal like this instead:
[
{
"id": 15707,
"name": "Jojo Leaf Eater - White",
"barcodes": ["6009702666853", "9317118010229",
"6009194082315", "6009149569649"]
}
]
How would I do this?
I've tried wrapping the call to fields.Nested()
in fields.List()
but that did not help.
If anybody has an idea of how to make this work, I'd really appreciate the help!
Thanks.
Background Information
Here are the relevant package versions:
Flask==1.1.1
flask-restplus==0.13.0
marshmallow==3.3.0
SQLAlchemy==1.3.11
simplejson==3.17.0
Database Classes
Here are the definitions of the SQLAlchemy classes:
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')
Alternative Implementation
I have a working implementation using Marshmallow.
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
This does precisely what I want. However I'd really prefer to use flask_restplus
models because they make the code for the actual API a lot neater.