Django + Factory Boy:如何使用命名参数来控制factory.Maybe + factory.RelatedFactory的行为

时间:2017-11-22 13:03:08

标签: python django factory-boy

有没有办法定义一个命名参数(不是模型属性)来控制 factory.Maybe 的行为?

例如:我想通过可能条件创建一个控制 RelatedFactory 创建的命名参数,我尝试这样做:

# factories.py
class Purchase(factory.DjangoModelFactory):
    user = factory.SubFactory('project.factories.UserFactory')
    total = uniform(10, 100)

    class Meta:
        model = Purchase

class UserFactory(factory.DjangoModelFactory):
    first_name = factory.Faker('first_name')
    last_name = factory.Faker('last_name')

    has_purchase = False
    purchases = factory.Maybe(
        'has_purchase',
        yes_declaration=factory.RelatedFactory(Purchase, 'purchase'),
        no_declaration=None
    )

    class Meta:
        exclude = ['has_purchase', 'purchases']
        model = User

# tests.py
user_without_purchase = UserFactory.create()
user_with_purchase = UserFactory.create(has_purchase=True)

似乎我无法通过命名参数更改 has_purchase 的值,它始终设置为False。我不知道是不是因为这两个字段都是在排除元属性中声明的。我必须将它们放在 exclude 中,否则 DjangoModelFactory 会在将其保存到数据库时尝试使用这些字段,这会导致完整性错误。

有办法吗?

2 个答案:

答案 0 :(得分:1)

工厂男孩似乎有一项功能来提供额外的参数,而无需将这些字段添加到exclude属性:http://factoryboy.readthedocs.io/en/latest/reference.html#simple-parameters

class UserFactory(factory.DjangoModelFactory):
    class Params:
        has_purchase = False

http://factoryboy.readthedocs.io/en/latest/reference.html#lazyattribute结合使用?

答案 1 :(得分:0)

详细说明ClémentDenoix的答案,我已经能够添加一个可选参数,以将值直接传递给子工厂(快捷方式之类):

class Y_Factory(DjangoModelFactory):
    class Meta:
        model = Y  # has a field named 'z'


class X_Factory(DjangoModelFactory):
    class Meta:
        model = X  # has a foreign key to Y

    class Params:
        z = None

    y = factory.lazy_attribute(lambda o: Y_Factory(z=o.z or 'default_z'))

现在,以下语法X_Factory(y=Y_Factory(z=z))可以简化为X_Factory(z=z)

但是有一个警告:使用这种语法会误导新用户,因为它错误地描述了数据结构。尽管如此,我还是决定在一种特殊情况下,这样的快捷方式可以很方便地从我的灯具中删除一些烦人的样板代码,值得进行权衡。