Reputation: 86
I want to use FactoryBoy with the User/Profile Pattern as described in its documentation.
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')
Now I would like to be able to either create a User by providing only the username like
u = UserFactory(username='alice')
and automatically get the username as the first_name (='Alice'
)in the profile
or the first_name like
u = UserFactory(profile__first_name='Bob')
and get the username (='bob'
)set according to the given first_name
or, if I am frisky provide both username and first_name and of course retain both
u = UserFactory(username='alice', profile__first_name='Bob')
So far I did not find the right spot to implement this behaviour. I tried overriding _generate()
, but found that this isn't the right spot, as my lazy attributes have already fired at this moment. Also I was not able to override __call__()
or __new__()
in my UserFactory
.
Maybe this is all because I am fairly new to python, so I would be thankful for any help to push me in the right direction.
Upvotes: 2
Views: 1096
Reputation: 86
Even though I feel a bit stupid answering my own first question here, I guess I found the answer myself:
It looks like the best method to override to achieve what I want is attributes
from BaseFactory
as all building/creating functions call this and I still get the 'pure' kwargs
as extra
to fiddle with them.
Maybe somebody still has a better answer but until then this is my version.
@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)
Upvotes: 2