Faker 使用 Factory Boy 创造的所有等值

All equal values created by Faker using Factory Boy

在 Django 项目中使用 Factory Boy 和 Faker,我注意到使用 Factory Boy 创建的对象和使用 Faker 创建名称(本例中为公司名称)不会为新对象创建唯一名称。

主要问题:我们在将 Faker 用作单独的库时是否使用错误(第一个示例),或者 Factory Boy 是否有一些固有的东西阻止 Faker 正常工作作为一个单独的库,当与 Factory Boy 一起使用时?

import factory
...

from faker import Faker
from faker.providers import company
...

fake = Faker('nl_NL')
fake.add_provider(company)


class PolicyBrandFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PolicyBrand

    name = fake.company()

结果(Pycharm 调试器屏幕截图): (重点是非唯一的公司名称)

在 Factory Boy 文档中我读到他们对 Faker 进行了包装,使用它我确实得到了独特的结果:

import factory
...


class PolicyBrandFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PolicyBrand

    name = factory.Faker('company', locale='nl_NL')

结果:

您正在使用 class 变量。 name 是在定义 class 时定义的,是单次调用 fake.company()

的结果
class PolicyBrandFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PolicyBrand

    name = fake.company()

如果这是一个简单的 Django 模型,我希望必须覆盖 __init__,但我对 factory.django.DjangoModelFactory 以及它的元class 魔法一无所知可能正在表演。

与 Django 表单和设置默认日期类似,name 值在首次定义 class 时设置。

您需要使用LazyAttribute

name = factory.LazyAttribute(lambda _: fake.company())

在 factory_boy 中支持使用 Faker 的方式是通过 factory.Faker 助手:

class PolicyBrandFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PolicyBrand

    name = factory.Faker('company', locale='nl_NL')

这也会将 Faker 的随机种子管理连接到 factory_boy 的随机种子。

如果你不想使用助手,你必须使用其中一个懒惰的助手:

fake = Faker('nl_NL')

class PolicyBrandFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PolicyBrand

    name = factory.LazyFunction(fake.company)
    name_alt = factory.LazyAttribute(lambda obj: fake.company())