18

如何定义一个依赖于其他字段的字段factory-boy

例如,我想定义一个email依赖于first nameandlast name的 an User

我尝试使用post_generation装饰器。但是,我的系统需要在创建实例之前定义电子邮件。

4

2 回答 2

27

使用LazyAttribute

来自文档:

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
于 2015-11-27T23:02:02.837 回答
0

您还可以将factory.SelfAttribute用于依赖于其他字段的字段。

在你的情况下,LazyAttribute工作正常,而且很清楚,但如果你需要做一些更复杂SelfAttribute的事情,这将是一个更好的选择。

例如,假设我们有一个名为 Course 的实体,其中包含 astart_dateend_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()

现在,让我们创建我们的 factory.py:

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我们可以引用正在构造的对象的另一个字段或其属性。

于 2021-09-23T01:56:11.360 回答