Marshmallow: Self-referencing schema - Post validate on root only

Created on 6 May 2019  路  2Comments  路  Source: marshmallow-code/marshmallow

[marshmallow v3]

Given a self-referencing schema (i.e. a MySchema where some fields are Nested('self'), I'd like to make a post_load validation step before returning my nested structure. Problem is: I'd like to perform this final validation step only on the root object and not in all the other nodes.
Do you know an easy solution to achieve this? Thanks!

question

All 2 comments

I would have assumed you could subclass the schema and declare the @post_load hook there, but self resolves to the subclass.

from marshmallow import fields, Schema, post_load


class MySchema(Schema):
    foo = fields.Nested('self', many=True)

class RootMySchema(MySchema):
    @post_load
    def bar(self, data):
        data['root'] = True
        return data

schema = RootMySchema()
obj = schema.load({'foo': [{'foo': []}]})
# {'foo': [{'foo': [], 'root': True}], 'root': True}

Using a string reference instead of "self" does not seem to work either. If you are using python 3 you can reference the class inside itself.

from marshmallow import fields, Schema, post_load


class MySchema(Schema):
    foo = fields.Nested(MySchema, many=True)

class RootMySchema(MySchema):
    @post_load
    def bar(self, data):
        data['root'] = True
        return data

schema = RootMySchema()
obj = schema.load({'foo': [{'foo': []}]})
# {'foo': [{'foo': []}], 'root': True}

If you are using python 2 you may have to override the recursive field on the top level schema as a work around.

from marshmallow import fields, Schema, post_load


class MySchema(Schema):
    foo = fields.Nested('MySchema', many=True)

class RootMySchema(MySchema):
    foo = fields.Nested(MySchema, many=True)

    @post_load
    def bar(self, data):
        data['root'] = True
        return data

schema = RootMySchema()
obj = schema.load({'foo': [{'foo': []}]})
# {'foo': [{'foo': []}], 'root': True}

Edit: Fixed missing @post_load.

I think there is a @post_load missing in the Python 3 example.

(Since this is MA3) I really hope the OP is not using Python 2.

Was this page helpful?
0 / 5 - 0 ratings