You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置marshmallow_sqlalchemy使模型序列化包含关联对象并掌握关联对象反序列化及Meta类相关配置

问题解决:SQLAlchemy与marshmallow_sqlalchemy关联序列化及配置说明

一、修改代码实现关联对象序列化输出

你当前的代码中,AuthorSchema默认不会自动序列化关联的books字段,再加上Author类里的books关系设置了lazy="dynamic"(返回Query对象而非列表),所以dump时不会包含书籍列表。要实现目标输出,我们可以从两方面调整:

修改后的完整代码

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref

engine = sa.create_engine("sqlite:///:memory:")
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()

class Author(Base):
    __tablename__ = "authors"
    id = sa.Column(sa.Integer, primary_key=True)
    name = sa.Column(sa.String, nullable=False)
    # 将lazy改为"select"(默认值),让author.books直接返回书籍列表而非Query对象
    books = relationship("Book", backref=backref("author", lazy="joined"), foreign_keys="Book.author_id", lazy="select")
    
    def __repr__(self):
        return "<Author(name={self.name!r})>".format(self=self)

class Book(Base):
    __tablename__ = "books"
    id = sa.Column(sa.Integer, primary_key=True)
    title = sa.Column(sa.String)
    author_id = sa.Column(sa.Integer, sa.ForeignKey("authors.id"))

Base.metadata.create_all(engine)

from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field, SQLAlchemyAutoSchema

class BookSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = Book
        load_instance = True
        include_fk = True

class AuthorSchema(SQLAlchemyAutoSchema):
    # 显式声明books字段,auto_field会自动关联BookSchema并识别many=True
    books = auto_field()
    class Meta:
        model = Author
        load_instance = True
        include_fk = True

author = Author(name="Chuck Paluhniuk")
author_schema = AuthorSchema()
book = Book(title="Fight Club", author=author)
book_schema = BookSchema()

session.add(author)
session.add(book)
session.commit()

dump_data_author = author_schema.dump(author)
print(dump_data_author)
dump_data_book = book_schema.dump(book)
print(dump_data_book)

关键调整说明

  1. 调整relationship的lazy属性:把books的lazy="dynamic"改为lazy="select",这样author.books会直接返回书籍对象列表,而非需要手动执行的Query对象,方便marshmallow序列化。
  2. 显式添加关联字段到Schema:在AuthorSchema中添加books = auto_field(),auto_field会自动识别这是一个一对多的关联关系,使用BookSchema来序列化每个书籍对象,并自动设置many=True。

如果不想修改lazy="dynamic",也可以用Method字段手动处理Query对象:

from marshmallow import fields

class AuthorSchema(SQLAlchemyAutoSchema):
    books = fields.Method("get_books")
    
    def get_books(self, obj):
        # 执行Query并序列化结果
        return BookSchema(many=True).dump(obj.books.all())
    
    class Meta:
        model = Author
        load_instance = True
        include_fk = True

二、关联对象的反序列化控制方法

反序列化就是将JSON数据转换为SQLAlchemy模型实例,包括关联对象的处理,这里举几个常见场景:

1. 同时创建主对象和关联对象

比如我们有如下输入数据:

input_data = {
    "name": "George Orwell",
    "books": [
        {"title": "1984"},
        {"title": "Animal Farm"}
    ]
}

要反序列化为包含书籍的Author实例,只需确保:

  • AuthorSchema和BookSchema的load_instance都设为True
  • 反序列化时传入session参数(用于持久化关联对象)
author = author_schema.load(input_data, session=session)
session.add(author)
session.commit()

2. 仅关联已存在的对象

如果不想创建新的书籍,只希望关联数据库中已存在的书籍,可以限制books字段只接收id:

class AuthorSchema(SQLAlchemyAutoSchema):
    books = auto_field(only=["id"])
    class Meta:
        model = Author
        load_instance = True
        include_fk = True

# 输入只需传入书籍id
input_data = {
    "name": "George Orwell",
    "books": [{"id": 1}, {"id": 2}]
}
author = author_schema.load(input_data, session=session)

3. 禁止反序列化关联字段

如果不想让客户端通过输入修改关联的书籍,可以将books设为dump_only:

class AuthorSchema(SQLAlchemyAutoSchema):
    books = auto_field(dump_only=True)
    class Meta:
        model = Author
        load_instance = True
        include_fk = True

三、Schema类Meta中常用配置项详解

在marshmallow_sqlalchemy的Schema类的Meta子类中,这些配置项可以帮你精细控制序列化和反序列化行为:

  • load_only:字段名列表,这些字段仅用于反序列化(从输入加载到模型),不会出现在序列化输出中。比如用户密码字段,只在创建/更新时接收,不会返回给客户端:

    class Meta:
        load_only = ("password",)
    
  • dump_only:字段名列表,这些字段仅用于序列化(从模型输出到JSON),反序列化时会忽略输入中的这些字段。比如数据库自动生成的id、created_at:

    class Meta:
        dump_only = ("id", "created_at")
    
  • exclude:字段名列表,这些字段完全不参与序列化和反序列化。比如内部备注字段不需要对外暴露:

    class Meta:
        exclude = ("internal_note",)
    
  • include:字段名列表,指定只包含这些字段参与序列化和反序列化,优先级高于exclude:

    class Meta:
        include = ("id", "name")
    
  • model:必填项,指定Schema对应的SQLAlchemy模型类,SQLAlchemyAutoSchema会基于这个模型自动生成字段。

  • load_instance:布尔值,设为True时,反序列化返回模型实例;设为False时返回普通字典。默认是False。

  • include_fk:布尔值,设为True时,会包含模型中的外键字段(比如author_id)在序列化和反序列化中,默认是False。

内容的提问来源于stack exchange,提问作者Amin Ba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:47:32