Marshmallow nesting post_load object creation

3k views Asked by At

I'm working on an API that handles nested data structures. When trying to use marshmallow i'm having trouble coming up with a solution to creating nested model instances with references to their parent instance. Marshmallow's post_load operates from the child to the parent in that order instead of parent to child. Is there a way to reverse this? I'd like to start with serializing the parent and pass it to the children as context.

var_test = {
    "id": 1,
    "name": "dad a",
    "children_a": [
        {
            "id": 2,
            "name": "child 1 - 2",
            "grand_children_a": [
                {
                    "id": 2,
                    "name": "child 1 - 2",
                }
            ]
        },
        {
            "id": 3,
            "name": "child 2 - 2",
        }
    ]
}

class ParentA(Schema):
    id = fields.Integer()
    name = fields.String()
    children_a = fields.Nested('ChildrenA', many=True)
    @post_load()
    def pl_handler(self, data):
        # create Parent A
        return data

class ChildrenA(Schema):
    id = fields.Integer()
    name = fields.String()
    grand_children_a = fields.Nested('GrandchildrenA', many=True)
    @post_load()
    def pl_handler(self, data):
        # create child of Parent A
        return data

class GrandchildrenA(Schema):
    id = fields.Integer()
    name = fields.String()
    @post_load()
    def pl_handler(self, data):
        # create child of ChildrenA
        return "grand child string"

var_s = ParentA()
var_s.load(var_test)
1

There are 1 answers

1
vivek barsagadey On

I think, you don't need post_load, as there is not class which is going to deserialize from this schema, so just remove it, it should work. If you plan to dserialize and hold it to any class, you need to return in post_load decorator, for example :

from marshmallow import Schema, fields, INCLUDE, post_load

class Author:
    def __init__(self, name, age):
        self.name = name
        self.age = age


class Book:
    def __init__(self, title, description, author):
        self.title = title
        self.description = description
        self.author = author

class AuthorSchema(Schema):
    name = fields.Str()
    age = fields.Int()

    @post_load
    def load_author(self, data, **kwargs):
        return Author(**data)


class BookSchema(Schema):
    title = fields.Str()
    description = fields.Str()
    author = fields.Nested(AuthorSchema)

    @post_load
    def load_book(self, data, **kwargs):
        return Book(**data)





data = {
    "title": "Test Book",
    "description": "A book Test",
    "author": {"name": "Vivek", "age": 35},
}


book = BookSchema(unknown=INCLUDE).load(data )
print(book)
print(book.author)
print(book.author.name)