python - 与工厂男孩的一对多关系
问题描述
我的 SQLAlchemy 模型中有一个多对一的关系。一份报告有许多样本(为简洁起见进行了简化):
class Sample(db.Model, CRUDMixin):
sample_id = Column(Integer, primary_key=True)
report_id = Column(Integer, ForeignKey('report.report_id', ondelete='CASCADE'), index=True, nullable=False)
report = relationship('Report', back_populates='samples')
class Report(db.Model, CRUDMixin):
report_id = Column(Integer, primary_key=True)
samples = relationship('Sample', back_populates='report')
现在在我的测试中,我希望能够生成一个Sample
实例,或者一个Report
实例,并填充缺失的关系。
class ReportFactory(BaseFactory):
class Meta:
model = models.Report
report_id = Faker('pyint')
samples = RelatedFactoryList('tests.factories.SampleFactory', size=3)
class SampleFactory(BaseFactory):
class Meta:
model = models.Sample
sample_id = Faker('pyint')
report = SubFactory(ReportFactory)
当我去创建这些实例时,工厂陷入了无限循环:
RecursionError: maximum recursion depth exceeded in comparison
但是,如果我尝试使用SelfAttribute
s 来停止无限循环,我最终会得到一个没有任何样本的报告:
class ReportFactory(BaseFactory):
samples = RelatedFactoryList('tests.factories.SampleFactory', size=3, report_id=SelfAttribute('..report_id'))
class SampleFactory(BaseFactory):
report = SubFactory(ReportFactory, samples=[])
report = factories.ReportFactory()
l = len(report.samples) # 0
但是,如果我生成一个Sample
with SampleFactory()
,它正确地有一个Report
对象。
我应该如何正确设计我的工厂,以便SampleFactory()
生成一个Sample
with associated Report
,并ReportFactory()
生成一个Report
with 2 associated Samples
,而没有无限循环?
解决方案
我的最终解决方案实际上比我想象的要简单得多:
class ReportFactory(BaseFactory):
class Meta:
model = models.Report
samples = RelatedFactoryList('tests.factories.SampleFactory', 'report', size=3)
class SampleFactory(BaseFactory):
class Meta:
model = models.Sample
report = SubFactory(ReportFactory, samples=[])
关键是使用第二个参数 toRelatedFactoryList
,在这种情况下,它必须对应于子级的父链接'report'
。此外,我使用SubFactory(ReportFactory, samples=[])
了 ,它确保如果我构建单个样本,不会在父节点上创建额外的样本。
使用此设置,我可以构建一个Report
与之关联的样本,并且该报告只有 1 个 child Sample
。相反,我可以构建一个Report
将自动填充 3 个子样本的。
我认为没有必要生成实际的模型 ID,因为一旦模型实际插入数据库,SQLAlchemy 就会自动执行此操作。但是,如果您想在不使用数据库的情况下执行此操作,我认为@Xelnor 的解决方案report_id = factory.SelfAttribute('report.id')
将起作用。
我遇到的唯一未解决的问题是覆盖报告上的样本列表(例如ReportFactory(samples = [SampleFactory()])
),但我已经打开了一个记录此错误的问题:https ://github.com/FactoryBoy/factory_boy/issues/636
推荐阅读
- python - python中的不规则间距pcolor图
- ios - Xcode 没有足够的内存在 App Store 上分发我的应用程序?
- java - 我怎样才能让这个文本字段和下拉菜单工作来做我想做的事?
- python - 如何将变量的值转换为日期时间对象
- c# - WPF 无法在 ComboBox 中选择启用的项目
- python - 使用一些偏移优化将一个数组复制到另一个数组
- istio - Istio 到外部集群的通信问题
- rocksdb - Rocksdbjava api库是否包含rocksdb数据库本身
- javascript - 在运行时创建资源后如何重新加载商店?
- nativescript - 如何完全以编程方式(没有 XML)初始化 NativeScript 应用程序?