带有 SubFactory 字段的 DjangoModelFactory 不创建新条目而是指向现有条目

DjangoModelFactory with a SubFactory field that does not create new entries but points to existing ones instead

假设我有:

class CompanyFactory(DjangoModelFactory):

    class Meta:
        model = Company

    name = factory.Faker("company")
    address = factory.Faker("address")


class InvoiceFactory(DjangoModelFactory):

    class Meta:
        model = Invoice

    company = factory.SubFactory(CompanyFactory)
    num = factory.Faker("numerify", text="#"*10)
    value_total = factory.Faker("random_number", digits=3)

当我 运行 使用 InvoiceFactory.create() 方法时,会创建一个新的发票条目。并且因为 Invoice "links"(外键)到 Company,所以也创建了一个新的公司条目。


问题:

重写此代码的正确方法是什么,以便在调用 InvoiceFactory.create() 时选择现有公司条目,而不是创建新条目?

您有两个选择:

始终选择现有公司:

class InvoiceFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Invoice
    company = factory.Iterator(models.Company.objects.all())

当创建第一个发票时,迭代器被延迟评估。但是,它将始终循环通过相同的工厂。

创建一些公司,然后重复使用:

首先,向您的 CompanyFactory 添加一个 django_get_or_create 属性:如果提供的 name 已经存在于数据库中,现有实例将被重用:

class CompanyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Company
        django_get_or_create = ['name']
    name = factory.Faker('company')
    address = factory.Faker('address')

然后,从常量列表(此处使用 factory.fuzzy.FuzzyChoice)为 name 字段提供值:

class InvoiceFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Invoice
    company = factory.SubFactory(
        CompanyFactory,
        name=factory.fuzzy.FuzzyChoice(['PSF', 'Django', 'The Spanish Inquisition']),
    )

创建前 3 个公司后,它们将被重新用于所有后续对象。