Hi,
I think post_dump with pass_original=True should pass the original object related to the data serialized and not a list of objects which this object belongs to.
from marshmallow import fields, post_dump, Schema
class DeviceSchema(Schema):
id = fields.String()
@post_dump(pass_original=True)
def __post_dump(self, data, obj):
print(obj) # <-- this is a list
devices = [dict(id=1), dict(id=2)]
DeviceSchema().dump(devices, many=True)
In the above example, the parameter obj is a list of devices rather than the device object itself.
What do you think?
I'm not sure on this. I think it's intuitive for pass_original to pass the target object unmodified (i.e. if a collection is being serialized, the "original object" is the collection), but I understand if others might disagree. I am very open to feedback on this.
I understand your point of view, but for me it's more intuitive and useful to receive the Device instance instead of a collection, and I think it would be more consistent because I can serialize a single device or a collection of devices and my scheme would work for both cases, I also could use my schema in a Nested field and it would work too because I know it always gets a Device instance as original object. Thanks!
+1 for @viniciuschiele's points. It is unexpected to receive a list instead of an object.
Since schema validators are designed to validate a single object instance unless pass_many is explicitly true, I think the intuitive behavior is for pass_original to return the corresponding original object instance unless pass_many is explicitly true.
Edit: false -> true
I was able to hack around this by using a temporary schema during serialization instead of many=True on the schema constructor.
I changed
data, _ = MySchema(many=True).dump(records)
return data
to
# HACK: Work around https://github.com/marshmallow-code/marshmallow/issues/315
class MyListSchema(Schema):
items = fields.List(fields.Nested(MySchema))
data, _ = MyListSchema().dump({'items': records})
return data['items']
Luckily this hack is tucked away into a class that gets inherited by all my models, so I don't have to duplicate it everywhere. This hack allows me to avoid duplicating my schemas just to override post_dump to handle the original list.
This could be fixed without breaking backwards compatibility by allowing a special value like pass_original='single' to opt in the desired behavior. I would recommend making this the default behavior in the next major version though.
OK, I think we can move forward with this. Let's go with the OP, summarized concisely by @deckar01 's comment above:
I think the intuitive behavior is for pass_original to return the corresponding original object instance unless pass_many is explicitly
falsetrue.
@stj has made a PR for this in #744.
EDIT: edit @deckar01 's comment to be correct.
Re-opening this, since #744 only implements this behavior for validates_schema. This still needs to be implemented for post_load and post_dump.
I'm afraid there is an issue with this fix: https://github.com/marshmallow-code/marshmallow/issues/1150.
Most helpful comment
Since schema validators are designed to validate a single object instance unless
pass_manyis explicitlytrue, I think the intuitive behavior is forpass_originalto return the corresponding original object instance unlesspass_manyis explicitlytrue.Edit:
false->true