序列化具有多个子对象的SQLAlchemy对象

2 投票
3 回答
3322 浏览
提问于 2025-04-18 14:48

我有一个SLQALchemy对象,我正在用marshmallow进行序列化。

这个对象有N个点赞和N条评论。它的结构是这样的:

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')

序列化器的样子是这样的:

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')

我在视图中尝试这样运行:

allParents = Parent.query.all()

然后用这个把它转成JSON格式:

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

但是当我尝试运行时,我遇到了一个错误 list indices must be integers, not str。这个错误来自于marshmallow/serializer.py。我在那里的日志中发现,marshmallow似乎在尝试访问一个评论列表中的text属性。它应该是先访问每个<Comment>,然后再访问它的text属性。

我在我的序列化器中是不是漏掉了什么?我知道在ParentSerializer中发送many=True参数是告诉marshmallow,它应该遍历一系列的<Parent>。有没有办法告诉marshmallow,它也应该期待有多个<Comment><Like>呢?

3 个回答

1

可以查看这个链接:https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html#association-object
在这里你可以使用自己定义的序列化函数。

 class Company(db.Model):
  __tablename__ = 'company'

  id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
  name = db.Column(db.String(255), nullable=False)
  users = relationship("CompanyUser", back_populates="company")

  def serialize(self):
   main =  { c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs }
   children = [user.serialize() for user in self.users] 
   main['users'] = children
   return  main

而且,在其他模型类中,你可以使用这种“通用”的可序列化方式:

 def serialize(self):
    return { c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs }
1

有没有办法告诉marshmallow,它也应该期待很多<Comment>或者<Like>呢?

另外,你可以这样做:

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

有没有办法告诉marshmallow,它也应该期待很多个<Comment>或者<Like>呢?

当然可以。你可以在Nested字段中加上many=True

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

撰写回答