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

SQLModel+FastAPI:添加计算字段且隐藏关联purchases字段的方法

解决方法

方法1:查询阶段直接计算聚合值(推荐)

直接在数据库查询时通过SQL聚合函数统计total_spent,不需要在模型中关联完整的purchases列表,既提升查询效率,也不会返回冗余数据。

示例代码:

from sqlmodel import select, func, join

# 构造查询语句,关联Purchase表计算总支出
statement = (
    select(
        Budget.id,
        Budget.name,
        Budget.monthly_income,
        # 用coalesce处理无采购记录的情况,默认返回0.0
        func.coalesce(func.sum(Purchase.price), 0.0).label("total_spent")
    )
    .outerjoin(Purchase, Budget.id == Purchase.budget_id)
    .group_by(Budget.id)
)

# 执行查询
results = session.exec(statement).all()

# 定义带统计字段的公开模型
class BudgetPublicWithStats(BudgetPublic):
    total_spent: float

# 将查询结果转换为响应模型
budget_stats_list = [BudgetPublicWithStats(**result._asdict()) for result in results]

返回的budget_stats_list仅包含预算基础信息和总支出,不会携带purchases字段。

方法2:私有字段+序列化排除

如果要在模型层面用@computed_field计算,可以添加私有_purchases字段,同时通过exclude=True标记该字段不参与序列化,避免返回给客户端。

示例代码:

from sqlmodel import Field, computed_field

class BudgetPublic(BudgetBase):
    id: int
    # 私有字段,设置exclude=True排除序列化
    _purchases: list[Purchase] = Field(..., exclude=True)

    @computed_field
    def total_spent(self) -> float:
        return sum(p.price for p in self._purchases) if self._purchases else 0.0

注意:查询时需要确保_purchases被正确加载(比如用selectinload(Budget._purchases)),但该字段不会出现在最终API响应中,仅保留计算后的total_spent。

方法3:分离模型职责

创建专门的统计模型,与包含purchases的模型解耦。在业务逻辑中手动计算统计值并填充到新模型,完全控制返回字段。

示例代码:

# 定义带多维度统计的公开模型
class BudgetPublicWithStats(BudgetPublic):
    total_spent: float
    average_purchase: float | None = None
    purchase_count: int = 0

# 业务逻辑处理
budget = session.get(Budget, budget_id, options=[selectinload(Budget.purchases)])
purchase_count = len(budget.purchases)
if purchase_count > 0:
    total_spent = sum(p.price for p in budget.purchases)
    average_purchase = total_spent / purchase_count
else:
    total_spent = 0.0
    average_purchase = None

# 构造响应模型
response = BudgetPublicWithStats(
    id=budget.id,
    name=budget.name,
    monthly_income=budget.monthly_income,
    total_spent=total_spent,
    average_purchase=average_purchase,
    purchase_count=purchase_count
)

这种方式适合需要多个统计维度的场景,完全自定义返回内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:40:03