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

FastAPI中Pydantic序列化时过滤关联is_delete=False子数据方案

解决方案

你可以根据业务需求选择以下任意一种实现方式:

方案1:ORM关系层全局过滤(最常用)

直接在Parent模型的relationship定义中增加关联过滤条件,之后所有场景下访问parent.children都会自动排除已标记删除的子数据,不需要额外修改查询和序列化逻辑,适合全局默认不返回软删除数据的场景。
首先修正原代码中Child模型的外键定义错误(原写法parent.id = Column(...)是非法语法,模型字段不能带点号),再修改relationship配置:

from sqlalchemy import Column, Integer, Boolean, ForeignKey
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()

class Parent(Base):
    __tablename__ = "parent"
    id = Column(Integer, primary_key=True, nullable=False)
    children = relationship(
        "Child",
        backref="parent",
        uselist=True,
        # 新增关联过滤条件,自动排除已删除子项
        primaryjoin="and_(Parent.id == Child.parent_id, Child.is_detele == False)"
    )

class Child(Base):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True, nullable=False)
    # 修正外键字段定义
    parent_id = Column(Integer, ForeignKey(Parent.id))
    is_detele = Column(Boolean, default=False)

修改完成后原有ParentBase序列化逻辑不需要做任何改动,返回结果会自动过滤掉is_detele=True的子数据。

方案2:查询时手动过滤(灵活度最高)

如果不需要全局过滤,仅在部分接口需要返回未删除的子数据,可以在查询数据库时手动过滤关联的children,通过contains_eager预加载过滤后的结果,不会影响其他场景下获取全量子数据。
代码示例:

from sqlalchemy.orm import contains_eager

# 构建查询语句,join关联子表并过滤软删除数据,预加载过滤后的children
parents = db.query(Parent)\
    .join(Parent.children)\
    .filter(Child.is_detele == False)\
    .options(contains_eager(Parent.children))\
    .all()

# 直接用原有ParentBase序列化即可
result = [ParentBase.from_orm(p).dict() for p in parents]

方案3:序列化层过滤(无侵入性)

如果不想修改ORM定义和查询逻辑,可以直接在Pydantic序列化模型中增加校验过滤逻辑,不管ORM加载的children是否包含已删除数据,最终序列化输出时都会自动过滤。
注意原来的children = list定义过于宽泛,建议先定义对应的子模型保证类型正确:

from pydantic import BaseModel, validator

class ChildBase(BaseModel):
    id: int
    parent_id: int
    is_detele: bool

    class Config:
        orm_mode = True

class ParentBase(BaseModel):
    id: int
    children: list[ChildBase]

    # 新增序列化校验器,过滤已删除子项
    @validator("children", pre=True)
    def filter_deleted_child(cls, children):
        return [child for child in children if not child.is_detele]

    class Config:
        orm_mode = True

注意事项
  • 原代码中is_detele疑似is_delete的拼写笔误,如果是笔误请统一修正所有引用位置的字段名,避免逻辑错误。
  • 方案1的全局过滤如果在某些场景需要获取包含已删除的全量子数据,可以在查询时使用noload或者自定义join条件绕过默认过滤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 21:57:24