Search code examples
pythonflasksqlalchemyflask-sqlalchemymarshmallow

Serialize SQLAlchemy Objects that have children with multiple children


I have an SLQALchemy object that I am serializing with marshmallow.

The object has N likes and N comments. It looks like this:

class Parent():

    __tablename__ = 'parent'

    title = Column(db.String(100), unique=True, nullable=False)
    description = Column(db.String(500))
    created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
    comments = relationship('Comment')
    likes = relationship('Like')

The serializers look like this:

class CommentSerializer(Serializer):
    class Meta:
        fields = ('id', 'text', 'created_at', 'parent_id')

class LikeSerializer(Serializer):
    class Meta:
        fields = ('id', 'created_at', 'parent_id')

class ParentSerializer(Serializer):
    comments = fields.Nested(CommentSerializer)
    likes = fields.Nested(LikeSerializer)

    class Meta:
        fields = ('id', 'title', 'description', 'comments', 'likes')

I try to run this in the view like so:

allParents = Parent.query.all()

And turn it into JSON with this:

return jsonify({"parents": ParentSerializer(allParents, many=True).data})

When I try and run that, I get an error list indices must be integers, not str. It comes from marshmallow/serializer.py. When I log some things in there, it appears that marshmallow is trying to access the text property of a list of <Comment>. It should be accessing each <Comment> individually then accessing the text property.

Am I missing something in my serializer(s)? I know sending the many=True argument in ParentSerializer tells marshmallow that it should iterate through a list of <Parent>. Is there a way to tell marshmallow that it should also expect many <Comment> or <Like>?


Solution

  • Is there a way to tell marshmallow that it should also expect many <Comment> or <Like>?

    Yes. You can also pass many=True to Nested fields.

    class ParentSerializer(Serializer):
        comments = fields.Nested(CommentSerializer, many=True)
        likes = fields.Nested(LikeSerializer, many=True)