2016-02-19 271 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