FactoryBoy覆盖属性

时间:2016-02-19 22:32:12

标签: python django factory-boy

我想将FactoryBoy与用户/配置文件模式一起使用,如文档中所述。

class ProfileFactory(DjangoModelFactory):
    class Meta:
        model = Profile     
    first_name = lazy_attribute(lambda o: faker.first_name())
    user = SubFactory('profiles.tests.factories.UserFactory', profile=None)

class UserFactory(DjangoModelFactory):
    class Meta:
        model = settings.AUTH_USER_MODEL
    username = lazy_attribute(lambda o: faker.first_name())
    profile = RelatedFactory(ProfileFactory, 'user')

现在我希望能够通过仅提供像

这样的用户名来创建用户
u = UserFactory(username='alice')

并自动将配置文件作为配置文件中的first_name(='Alice'

或first_name like

u = UserFactory(profile__first_name='Bob')

并获取根据给定的first_name

设置的用户名(='bob'

或者,如果我是活泼的,请同时提供username和first_name,当然还要保留两者

u = UserFactory(username='alice', profile__first_name='Bob')

到目前为止,我找不到实施此行为的正确位置。我尝试重写_generate(),但发现这不是正确的位置,因为我的懒惰属性此时已经被解雇了。此外,我无法覆盖__call__()中的__new__()UserFactory

也许这就是因为我对python很新,所以我会感谢任何帮助推动我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:1)

即使我觉得在这里回答我自己的第一个问题有点愚蠢,但我想我自己找到了答案:

attributes开始,覆盖以实现我想要的最佳方法是BaseFactory,因为所有构建/创建函数都会调用此方法,我仍然可以获得'纯'kwargs extra摆弄他们。

也许有人还有更好的答案,但在此之前这是我的版本。

@classmethod
def attributes(cls, create=False, extra=None):
    if extra:
        if 'profile__first_name' in extra and 'username' not in extra:
            extra['username'] = extra['profile__first_name'].lower()
        elif 'username' in extra and 'profile__first_name' not in extra:
            extra['profile__first_name'] = extra['username'].title()

    return super().attributes(create, extra)