如何创建一个具有共享某些属性的外键实例的工厂 - 但该属性在父级上不存在?

How does one create a Factory with foreign key instances that share certain attributes - but that attribute does not exist on parent?

我正在寻找使用 FactoryBoy 来确保使用相同实例生成具有外键的模型,这些模型间接共享外键的其他模型(我意识到这很难理解,这是一个代码示例):

from django.db import models
import factory


class Foo(models.Model):
    name = models.CharField(max_length=32)

class Bar(models.Model):
    foo = models.ForeignKey(Foo, on_delete=models.PROTECT)

class Baz(models.Model):
    foo = models.ForeignKey(Foo, on_delete=models.PROTECT)

class HasBarAndBaz(models.Model):
    bar = models.ForeignKey(Bar, on_delete=models.PROTECT)
    baz = models.ForeignKey(Baz, on_delete=models.PROTECT)

class HasBarAndBazFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = HasBarAndBaz

    bar = factory.SubFactory(BarFactory)
    baz = factory.SubFactory(BazFactory)

这里的愿望是确保发生以下情况

has_bar_and_baz = HasBarAndBazFactory()
has_bar_and_baz.bar.foo === has_bar_and_baz.baz.foo # should be True

我能想到几个解决方案,但我很想知道是否有“FactoryBoy” 这样做的方法,无需编写接受 product_line kwarg 的包装函数 并通过它。

我考虑过使用 RelatedFactory,然后将其作为默认 foo kwarg 引用到 SubFactories,但是在基础工厂之后生成了 RelatedFactory。

我尝试了几个失败的解决方案,但到目前为止这似乎是有效的 - 也有 foo kwarg 是可选的好处,这在我的一些尝试中没有奏效:

class HasBarAndBazFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = HasBarAndBaz
        exclude = ('foo',)

    foo = factory.SubFactory(FooFactory)
    bar = factory.SubFactory( BarFactory, foo=factory.SelfAttribute('..foo'))
    baz = factory.SubFactory( BazFactory, foo=factory.SelfAttribute('..foo'))

我知道 exclude,但我不知道您可以声明原始模型中不存在的子工厂属性 - 我假设 RelatedFactory 必须用于那些。

您有两个选择:将 Bar 优先于 Baz;或公开共享项目。

第一个选项(用作HasBarAndBazFactory(bar__foo=some_foo)):

class HasBarAndBazFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.HasBarAndBaz

    bar = factory.SubFactory(BarFactory)
    baz = factory.SubFactory(BazFactory, foo=factory.SelfAttribute('..bar.foo'))

第二个选项(用作HasBarAndBazFactory(foo=some_foo)):

class HasBarAndBazFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.HasBarAndBaz

    class Params:
        foo = models.SubFactory(FooFactory)

    bar = factory.SubFactory(BarFactory, foo=factory.SelfAttribute('..foo'))
    baz = factory.SubFactory(BazFactory, foo=factory.SelfAttribute('..foo'))

(目前)还没有办法声明 bar__foobaz__foo 应该始终具有相同的值;你必须在你的食谱中明确。