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

FastAPI中如何将含多字段header的Pydantic模型存入SQLAlchemy

解决FastAPI中SQLAlchemy处理嵌套Header字段的问题

在FastAPI中处理嵌套的header字段,有两种常见方案,可根据你的使用场景选择:


方案一:将Header的每个属性作为数据库单独列(适合需单独查询Header字段的场景)

如果需要对Header里的属性做单独筛选、排序等操作,建议把每个属性拆成数据库表的单独列。

1. 修正SQLAlchemy模型

把Header中的每个属性作为可选列添加到MainActionTable(示例仅列4个,需补充剩余16个):

class MainActionTable(Base):
    __tablename__ = 'MainActionTable'
    id = sql.Column(sql.Integer, primary_key=True, index=True)
    test_id = sql.Column(sql.String)
    status = sql.Column(sql.String)
    row_index = sql.Column(sql.Integer)  # 修正为int,匹配Pydantic模型类型
    test_type = sql.Column(sql.String)
    execute = sql.Column(sql.Boolean, nullable=True)  # 若存布尔值,后续需做字符串转布尔处理
    worksheet = sql.Column(sql.String)
    date_created = sql.Column(sql.DateTime, default=dt.datetime.utcnow)
    date_last_updated = sql.Column(sql.DateTime, default=dt.datetime.utcnow)
    
    # Header对应的字段,全部设为可选
    header_id = sql.Column(sql.String, nullable=True)
    header_execute = sql.Column(sql.String, nullable=True)
    header_task_name = sql.Column(sql.String, nullable=True)
    header_standard = sql.Column(sql.String, nullable=True)
    # 补充剩余16个Header属性,命名规则保持一致

2. 完善Pydantic模型

确保MainActionCreate包含所有必填字段:

class MainActionCreate(pydantic.BaseModel):
    worksheet: str
    row_index: int
    test_id: str
    test_type: str
    execute: str
    header: AdditionalData
    status: Optional[str] = None

3. 修正保存逻辑

将Header的属性拆分后赋值到数据库模型:

def create_action_point(db: orm.Session, action_create: MainActionCreate):
    # 提取Header数据并转换为数据库列对应的键名
    header_dict = action_create.header.dict()
    action_data = action_create.dict(exclude={"header"})
    
    # 合并Header字段到主数据
    action_data.update({
        "header_id": header_dict.get("ID"),
        "header_execute": header_dict.get("Execute"),
        "header_task_name": header_dict.get("TaskName"),
        "header_standard": header_dict.get("Standard"),
        # 补充剩余16个Header字段的映射
    })
    
    # 处理execute字段的类型转换(如果数据库存布尔值)
    action_data["execute"] = action_data["execute"].upper() == "ON"
    
    action_point = MainActionTable(**action_data)
    db.add(action_point)
    db.commit()
    db.refresh(action_point)
    return action_point

# 调用示例
action_tuple = data['action_case']
for x in action_tuple:
    # 处理原始数据中的header元组,转换为AdditionalData对象
    header_data = dict(zip(AdditionalData.model_fields.keys(), x['header']))
    create_data = MainActionCreate(
        worksheet=x['worksheet'],
        row_index=x['row_index'],
        test_id=x['test_id'],
        test_type=x['test_type'],
        execute=x['execute'],
        header=AdditionalData(**header_data),
        status=x['status']
    )
    create_action_point(db=db, action_create=create_data)

4. 读取时的映射

为让ORM模型自动转换为Pydantic模型,在MainAction中添加字段验证器组装Header数据:

class MainAction(pydantic.BaseModel):
    worksheet: str
    row_index: int
    test_id: str
    test_type: str
    execute: str
    header: AdditionalData
    status: Optional[str] = None

    class Config:
        orm_mode = True

    @pydantic.field_validator('header', mode='before')
    def assemble_header(cls, v, values):
        # 从ORM模型读取时,组装Header数据
        if isinstance(v, dict):
            return v
        return AdditionalData(
            ID=values.data.get('header_id'),
            Execute=values.data.get('header_execute'),
            TaskName=values.data.get('header_task_name'),
            Standard=values.data.get('header_standard'),
            # 补充剩余16个字段的映射
        )

方案二:用JSON类型存储整个Header(推荐,适合Header字段多、无需单独查询的场景)

如果不需要对Header里的单个属性做数据库查询,直接把整个Header序列化为JSON存储,代码更简洁,维护成本更低。

1. 修正SQLAlchemy模型

添加一个header列,类型为sql.JSON:

class MainActionTable(Base):
    __tablename__ = 'MainActionTable'
    id = sql.Column(sql.Integer, primary_key=True, index=True)
    test_id = sql.Column(sql.String)
    status = sql.Column(sql.String)
    row_index = sql.Column(sql.Integer)  # 修正为int,匹配Pydantic类型
    test_type = sql.Column(sql.String)
    execute = sql.Column(sql.Boolean, nullable=True)  # 若存布尔值需转换
    worksheet = sql.Column(sql.String)
    header = sql.Column(sql.JSON)  # 用JSON类型存储整个Header数据
    date_created = sql.Column(sql.DateTime, default=dt.datetime.utcnow)
    date_last_updated = sql.Column(sql.DateTime, default=dt.datetime.utcnow)

2. 完善Pydantic模型

MainActionCreate直接继承MainAction即可:

class MainActionCreate(MainAction):
    pass

3. 简化保存逻辑

Pydantic会自动将AdditionalData转换为字典,SQLAlchemy的JSON列会直接存储:

def create_action_point(db: orm.Session, action_create: MainActionCreate):
    action_data = action_create.dict()
    # 处理execute字段的类型转换(如果数据库存布尔值)
    action_data["execute"] = action_data["execute"].upper() == "ON"
    action_point = MainActionTable(**action_data)
    db.add(action_point)
    db.commit()
    db.refresh(action_point)
    return action_point

# 调用示例
action_tuple = data['action_case']
for x in action_tuple:
    # 处理原始数据中的header元组,转换为AdditionalData对象
    header_data = dict(zip(AdditionalData.model_fields.keys(), x['header']))
    create_data = MainActionCreate(
        worksheet=x['worksheet'],
        row_index=x['row_index'],
        test_id=x['test_id'],
        test_type=x['test_type'],
        execute=x['execute'],
        header=AdditionalData(**header_data),
        status=x['status']
    )
    create_action_point(db=db, action_create=create_data)

4. 读取自动转换

因为Pydantic的orm_mode已开启,读取ORM模型时,JSON列的字典会自动转换为AdditionalData对象,无需额外处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:42:25