如何使用 factory-boy
定义依赖于其他字段的字段?
例如,我想定义一个依赖于 User
的 first name
和 last name
的 email
。
我尝试使用 post_generation
装饰器。但是,我的系统要求在创建实例之前定义电子邮件。
如何使用 factory-boy
定义依赖于其他字段的字段?
例如,我想定义一个依赖于 User
的 first name
和 last name
的 email
。
我尝试使用 post_generation
装饰器。但是,我的系统要求在创建实例之前定义电子邮件。
来自文档:
LazyAttribute是扩展工厂的一种简单但极其强大的构建组件。
它以要调用的方法(通常是lambda)作为参数;该方法应将正在构建的对象作为唯一参数接受,并返回一个值。
class UserFactory(factory.Factory):
class Meta:
model = User
username = 'john'
email = factory.LazyAttribute(lambda o: '%s@example.com' % o.username)
或者使用lazy_attribute修饰符。
来自文档:
如果简单的lambda表达式不够用,您可以使用lazy_attribute()装饰器。
这将修饰一个实例方法,该方法应接受一个self参数;方法的名称将用作填充返回值的属性的名称:
class UserFactory(factory.Factory)
class Meta:
model = User
name = u"Jean"
@factory.lazy_attribute
def email(self):
# Convert to plain ascii text
clean_name = (unicodedata.normalize('NFKD', self.name)
.encode('ascii', 'ignore')
.decode('utf8'))
return u'%s@example.com' % clean_name
LazyAttribute
效果很好,而且很清晰,但如果您需要做一些更复杂的操作,SelfAttribute
将是更好的选择。start_date
和end_date
。每个课程都有一个期末考试,必须在课程开始后参加,并在课程结束前完成。然后,model.py应该如下所示:class Course(models.Model):
start_date = models.DateTimeField(auto_now_add=False, blank=False)
end_date = models.DateTimeField(auto_now_add=False, blank=False)
class Test(models.Model):
course = models.ForeignKey(
to=Course, blank=False, null=False, on_delete=models.CASCADE
)
date = models.DateField()
class CourseFactory(DjangoModelFactory):
class Meta:
model = Course
start_date = factory.Faker(
"date_time_this_month", before_now=True, after_now=False, tzinfo=pytz.UTC
)
end_date = factory.Faker(
"date_time_this_month", before_now=False, after_now=True, tzinfo=pytz.UTC
)
class TestFactory(DjangoModelFactory):
class Meta:
model = Test
date = factory.Faker(
"date_between_dates",
date_start=factory.SelfAttribute('..course.start_date'),
date_end=factory.SelfAttribute('..course.end_date')
)
course = factory.SubFactory(CourseFactory)
TestFactory
中所看到的,我们可以引用正在构建的对象的另一个字段或其属性。date = factory.Faker(
应该改为 date = factory.Maybe(
吗? - thoroc