如何使用 Django 中的 Factory Boy 将值传递给依赖模型?
How to I pass values into dependent models with Factory Boy in Django?
我正在开发一个开源的 django 网络应用程序,我希望使用 Factory Boy 来帮助我为一些测试设置模型,但在阅读文档和查看示例几个小时后,我认为我要认输在这里问
我有一个看起来有点像这样的客户模型:
class Customer(models.Model):
def save(self, *args, **kwargs):
if not self.full_name:
raise ValidationError('The full_name field is required')
super(Customer, self).save(*args, **kwargs)
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='customer',
null=True
)
created = models.DateTimeField()
created_in_billing_week = models.CharField(max_length=9)
full_name = models.CharField(max_length=255)
nickname = models.CharField(max_length=30)
mobile = models.CharField(max_length=30, default='', blank=True)
gocardless_current_mandate = models.OneToOneField(
BillingGoCardlessMandate,
on_delete=models.SET_NULL,
related_name='in_use_for_customer',
null=True,
)
我也在使用来自 django.contrib.auth 的标准 Django 用户模型。
这是我的工厂代码:
class UserFactory(DjangoModelFactory):
class Meta:
model = get_user_model()
class CustomerFactory(DjangoModelFactory):
class Meta:
model = models.Customer
full_name = fake.name()
nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])
created = factory.LazyFunction(timezone.now)
created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))
mobile = fake.phone_number()
user = factory.SubFactory(UserFactory, username=nickname,
email="{}@example.com".format(nickname))
就我而言,我希望能够产生这样的客户
CustomerFactory(fullname="Joe Bloggs")
并使用正确的用户名和电子邮件地址生成相应的用户。
现在,我收到此错误:
AttributeError: The parameter full_name is unknown. Evaluated attributes are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com'}, definitions are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com', 'username': <DeclarationWrapper for <factory.declarations.LazyAttribute object at 0x111d999e8>>}.
我认为这是因为我依赖于客户中的惰性属性,在创建用户工厂之前不会调用它。
如果我希望能够使用工厂创建 Customer 模型实例,并且如上所述具有相应的用户,我应该如何这样做?
完整模型可见 here on the github repo
在这种情况下,最好的方法是从 the customer declarations:
中选取值
class CustomerFactory(DjangoModelFactory):
class Meta:
model = models.Customer
full_name = factory.Faker('name')
nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])
created = factory.LazyFunction(timezone.now)
created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))
mobile = factory.Faker('phone_number')
user = factory.SubFactory(
UserFactory,
username=factory.SelfAttribute('..nickname'),
email=factory.LazyAttribute(lambda u: "{}@example.com".format(u.username)))
)
此外,使用 factory.Faker('field_name')
为每个实例获取随机值:class 声明 中的 fullname = fake.name()
行等同于:
DEFAULT_FULL_NAME = fake.name()
class CustomerFactory(DjangoModelFactory):
full_name = DEFAULT_FULL_NAME
class Meta:
model = models.customer
而 factory.Faker('name')
等同于:
class CustomerFactory(DjangoModelFactory):
full_name = factory.LazyFunction(fake.name)
class Meta:
model = models.customer
即 fake.name()
将为使用该工厂构建的每个模型提供不同的名称。
我正在开发一个开源的 django 网络应用程序,我希望使用 Factory Boy 来帮助我为一些测试设置模型,但在阅读文档和查看示例几个小时后,我认为我要认输在这里问
我有一个看起来有点像这样的客户模型:
class Customer(models.Model):
def save(self, *args, **kwargs):
if not self.full_name:
raise ValidationError('The full_name field is required')
super(Customer, self).save(*args, **kwargs)
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='customer',
null=True
)
created = models.DateTimeField()
created_in_billing_week = models.CharField(max_length=9)
full_name = models.CharField(max_length=255)
nickname = models.CharField(max_length=30)
mobile = models.CharField(max_length=30, default='', blank=True)
gocardless_current_mandate = models.OneToOneField(
BillingGoCardlessMandate,
on_delete=models.SET_NULL,
related_name='in_use_for_customer',
null=True,
)
我也在使用来自 django.contrib.auth 的标准 Django 用户模型。
这是我的工厂代码:
class UserFactory(DjangoModelFactory):
class Meta:
model = get_user_model()
class CustomerFactory(DjangoModelFactory):
class Meta:
model = models.Customer
full_name = fake.name()
nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])
created = factory.LazyFunction(timezone.now)
created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))
mobile = fake.phone_number()
user = factory.SubFactory(UserFactory, username=nickname,
email="{}@example.com".format(nickname))
就我而言,我希望能够产生这样的客户
CustomerFactory(fullname="Joe Bloggs")
并使用正确的用户名和电子邮件地址生成相应的用户。
现在,我收到此错误:
AttributeError: The parameter full_name is unknown. Evaluated attributes are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com'}, definitions are {'email': '<factory.declarations.LazyAttribute object at 0x111d999e8>@example.com', 'username': <DeclarationWrapper for <factory.declarations.LazyAttribute object at 0x111d999e8>>}.
我认为这是因为我依赖于客户中的惰性属性,在创建用户工厂之前不会调用它。
如果我希望能够使用工厂创建 Customer 模型实例,并且如上所述具有相应的用户,我应该如何这样做?
完整模型可见 here on the github repo
在这种情况下,最好的方法是从 the customer declarations:
中选取值class CustomerFactory(DjangoModelFactory):
class Meta:
model = models.Customer
full_name = factory.Faker('name')
nickname = factory.LazyAttribute(lambda obj: obj.full_name.split(' ')[0])
created = factory.LazyFunction(timezone.now)
created_in_billing_week = factory.LazyAttribute(lambda obj: str(get_billing_week(obj.created)))
mobile = factory.Faker('phone_number')
user = factory.SubFactory(
UserFactory,
username=factory.SelfAttribute('..nickname'),
email=factory.LazyAttribute(lambda u: "{}@example.com".format(u.username)))
)
此外,使用 factory.Faker('field_name')
为每个实例获取随机值:class 声明 中的 fullname = fake.name()
行等同于:
DEFAULT_FULL_NAME = fake.name()
class CustomerFactory(DjangoModelFactory):
full_name = DEFAULT_FULL_NAME
class Meta:
model = models.customer
而 factory.Faker('name')
等同于:
class CustomerFactory(DjangoModelFactory):
full_name = factory.LazyFunction(fake.name)
class Meta:
model = models.customer
即 fake.name()
将为使用该工厂构建的每个模型提供不同的名称。