2016-02-19 227 views
1

我想使用FactoryBoy和用户/配置文件模式,如其文档中所述。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'

或名字像

u = UserFactory(profile__first_name='Bob') 

并获得用户名(='bob')根据给定的FIRST_NAME

,或者,如果我是活泼的同时提供用户名和FIRST_NAME,当然同时保留

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

到目前为止,我没有找到实现这一行为的正确位置设置。我试图覆盖_generate(),但发现这不是正确的地方,因为我的懒惰属性此刻已经开了。此外,我无法在UserFactory中覆盖__call__()__new__()

也许这都是因为我对python相当陌生,所以我会非常感谢任何帮助将我推向正确的方向。

回答

1

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

它看起来像最好的方法重写以达到我想要的是BaseFactoryattributes所有建筑/创建函数调用这个,我仍然得到'纯'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) 
+0

看起来像一个完全合理的答案,您的原始问题。如果有效,就接受它。其他人可能会觉得它有用。 – Oin