Reputation: 727
Sorry if this has been asked before, I could not actually find a solution or similar question (maybe using the wrong words).
I'm updating an existing Flask API that receives data from a client we don't control (can't change the JSON data format), using marshmallow and peewee.
The data format comes this way:
{
"site_id": "0102931",
"update_date": "2018/02/11-09:33:23",
"updated_by": "chan1",
"crc": "a82131cf232ff120aaf00001293f",
"data": [{"num": 1,
"id": "09213/12312/1",
"chain": "chain2",
"operator": "0000122",
"op_name": "Fred",
"oid": "12092109300293"
},
{"num": 2,
"id": "09213/12312/2",
"chain": "chain1",
"operator": "0000021",
"op_name": "Melissa",
"oid": "8883390393"
}]
}
We are not interested about anything in the main block, but the site_id, which must be copied into each of the objects in the list when deserializing to create the models and store the data.
This is the model in peeewee:
class production_item(db.Model):
site_id = TextField(null=False)
id_prod = TextField(null=False)
num = SmallIntegerField(null=False)
chain = TextField(null=False)
operator = TextField(null=False)
operator_name = TextField(null=True)
order_id = TextField(null=False)
And this is the marshamallow schema:
class prodItemSchema(Schema):
num=String(required=True)
id=String(required=True)
chain=String(required=True)
operator=String(required=True)
op_name=String(required=False, allow_none=True)
oid=String(required=False, allow_none=True)
I can't find a way to pass the site-id from the main structure with load() method and pre-load / post-load decorators for the prodItemSchema, so the model can't be created. Also, I'd like for marshmallow to validate the whole structure for me, not doing in two parts between the resource and the schema, as they are doing in the code right now.
But can't find a way in the documentation to make something like this, is that possible?
Upvotes: 5
Views: 2819
Reputation: 764
In marshmallow it's possible to pass values from a parent scheme to its children before serialization by using the pre_dump decorator on the parent scheme to set the context. Once the context is set, a function field can be used to obtain the value from the parent.
class Parent(Schema):
id = fields.String(required=True)
data = fields.Nested('Child', many=True)
@pre_dump
def set_context(self, parent, **kwargs):
self.context['site_id'] = parent['id']
return data
class Child(Schema):
site_id = fields.Function(inherit_from_parent)
def inherit_from_parent(child, context):
child['site_id'] = context['site_id']
return child
Upvotes: 7