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

如何在SQLAlchemy声明式模型中正确配置FactoryBoy SubFactory?

解决FactoryBoy SubFactory与SQLAlchemy外键关联的适配问题

这个问题我之前也碰到过,核心原因是你把SubFactory返回的Group模型对象直接赋值给了需要整数ID的group_id字段,SQLAlchemy没法把对象转换成数据库能识别的整数类型,所以才会抛出can't adapt type 'Group'的错误。下面给你两种解决思路,以及修正后的完整代码:

一、先修正SQLAlchemy模型(补充必要配置)

首先确保模型指定了表名,同时推荐补充ORM关系字段(方便后续关联查询,也能让FactoryBoy更好地处理关联):

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()  # 注意统一变量名大小写,避免拼写错误

class Group(Base):
    __tablename__ = "groups"  # 必须指定表名,避免SQLAlchemy自动生成的表名出现问题
    group_id = Column(Integer, autoincrement=True, primary_key=True)
    # 补充反向关联字段,方便从Group查询关联的Person
    people = relationship("Person", back_populates="group")

class Person(Base):
    __tablename__ = "people"
    person_id = Column(Integer, autoincrement=True, primary_key=True)
    group_id = Column(Integer, ForeignKey(Group.group_id))
    # 补充正向关联字段,方便从Person获取关联的Group对象
    group = relationship("Group", back_populates="people")

二、两种正确的Factory配置方式

方式1:利用ORM关系字段赋值(推荐)

直接给Person模型的关系字段group赋值SubFactory,FactoryBoy会自动处理外键group_id的填充:

import factory
from factory.alchemy import SQLAlchemyModelFactory
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from your_module import Base, Person, Group

# 配置Factory使用的数据库Session
engine = create_engine("postgresql://your_user:your_password@your_host/your_db")  # 替换为你的数据库连接串
Session = sessionmaker(bind=engine)
db_session = Session()

# 定义基础Factory类,统一配置Session
class BaseFactory(SQLAlchemyModelFactory):
    class Meta:
        model = Base
        sqlalchemy_session = db_session
        sqlalchemy_session_persistence = "commit"  # 测试场景也可以用"rollback"避免污染数据库

class GroupFactory(BaseFactory):
    class Meta:
        model = Group

class PersonFactory(BaseFactory):
    class Meta:
        model = Person
    # 直接给关系字段group赋值SubFactory,FactoryBoy会自动生成Group并填充group_id
    group = factory.SubFactory(GroupFactory)

方式2:直接生成外键ID值

如果你不想依赖ORM关系字段,可以通过LazyAttribute从SubFactory生成的对象中提取ID:

class PersonFactory(BaseFactory):
    class Meta:
        model = Person
    # 先生成Group实例,再提取它的group_id赋值给字段
    group_id = factory.LazyAttribute(lambda _: GroupFactory().group_id)

三、测试代码的正确用法

现在运行测试代码就不会报错了:

from your_module import PersonFactory

# 创建Person时会自动创建关联的Group,并正确填充group_id
person = PersonFactory.create()
print(person.group_id)  # 输出关联Group的ID
print(person.group)     # 如果用方式1配置了关系字段,这里会返回对应的Group对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:51:11