如何在棉花糖-SQLAlchemy中处理嵌套关系

Ant*_*eri 6 python sqlalchemy marshmallow

我有一个项目,试图使用marshmallow-sqlalchemy包将数据从JSON加载到Sqlalchemy数据库中。该模型与子模型包含一对多关系。

使用经典著作的示例,其中包含许多书籍:

class Book(Base):
    __tablename__ = "book"
    id = Column(Integer, primary_key=True)
    title = Column(String(50))

    author_id = Column(Integer, ForeignKey("author.id"), nullable=False)
    author = relationship("Author", backref=backref("books"))


class Author(Base):
    __tablename__ = "author"
    id = Column(Integer, primary_key=True)
    name = Column(String(250))

    books = relationship("Author", back_populates="author")


class BookSchema(ModelSchema):
    class Meta:
        model = Book
        sqla_session = Session


class AuthorSchema(ModelSchema):
    class Meta:
        model = Author
        sqla_session = Session

    books = fields.Nested(BookSchema, many=True)
Run Code Online (Sandbox Code Playgroud)

输入的JSON是

{
    "name": "Author A",
    "books": [
        {"title": "Book 1"},
        {"title": "Book 2"}
    ]
 }
Run Code Online (Sandbox Code Playgroud)

当我尝试加载该JSON时,请使用以下命令:

json_repr = {...}
author_schema = AuthorSchema()
obj_repr = author_schema.load(json_repr)
Run Code Online (Sandbox Code Playgroud)

当它试图反序列化文档时说Book是一种不可散列的类型,这引发了一个异常。

发生了什么,我相信解串器正在尝试使用类似

obj = model(**data)
Run Code Online (Sandbox Code Playgroud)

不适用于一对多关系,因为列表的实例需要append()编辑到Author.books属性。

我一直找不到在网络上任何地方都可以使用的实例,我所看到的每个实例似乎都在嵌套一个实例,而不是一个列表。有没有建议使用棉花糖sqlalchemy完成此操作的方法,还是应该恢复使用直接棉花糖包,并使用@post_load方法手动附加关系对象。

And*_*len 9

我遇到了与这篇旧帖子类似的问题。设法在一个稍微不同的框架 Flask + SQLAlchemy + Marshmallow-SQLAlchemy(版本 2)下修复了这篇文章。发布代码以防万一。

大多数变化是为了 models.py

  1. 换线 books = relationship("Book", back_populates="author")
  2. 使用back_populates而不是backref因为我收到错误sqlalchemy.exc.ArgumentError: Error creating backref 'books' on relationship 'Book.author': property of that name exists on mapper 'mapped class Author->author

模型.py

class Book(db.Model):
    __tablename__ = "book"
    id = Column(db.Integer, primary_key=True)
    title = Column(db.String(50))

    author_id = Column(db.Integer, db.ForeignKey("author.id"), nullable=False)
    author = relationship("Author", back_populates="books")


class Author(db.Model):
    __tablename__ = "author"
    id = Column(db.Integer, primary_key=True)
    name = Column(db.String(250))

    books = relationship("Book", back_populates="author")
Run Code Online (Sandbox Code Playgroud)

schemas.py - 大体相同

class BookSchema(ModelSchema):
    class Meta:
        model = Book
        sqla_session = db.session


class AuthorSchema(ModelSchema):
    class Meta:
        model = Author
        sqla_session = db.session

    books = fields.Nested(BookSchema, many=True)
Run Code Online (Sandbox Code Playgroud)

视图.py

@api.route('/author/', methods=['POST'])
def new_author():
    schema = AuthorSchema()
    author = schema.load(request.get_json())
    db.session.add(author.data) # version 2 marshmallow
    db.session.commit()
    return jsonify({"success": True})
Run Code Online (Sandbox Code Playgroud)