Search code examples
djangofactory-boy

How to assign the attribute of SubFactory instead of the SubFactory itself


I need the attribute of the SubFactory instead of the object created by it.

# models.py
class User:
    pass

class UserProfile:
    user = models.OneToOneField(User)

class Job:
    user = models.ForeignKey(User)


# factories.py
class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

class UserProfileFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = UserProfile

    user = factory.SubFactory(UserFactory)

class JobFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Job

    # for certain reasons, I want to use UserProfileFactory here but get the user generated from it
    user = factory.SubFactory(UserProfileFactory).user  # doesn't work but you get the idea

Solution

  • The best way is to combine class Params and factory.SelfAttribute:

    
    class JobFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = Job
    
        class Params:
            profile = factory.SubFactory(ProfileFactory)
    
        user = factory.SelfAttribute("profile.user")
    

    A parameter is used inside the factory, but discarded before calling the model.

    This way:

    • You can provide a profile to the factory if you have it around: JobFactory(profile=foo)
    • You can set some sub-field of the profile' user: JobFactory(profile__user__username="john.doe")