munsu
munsu

Reputation: 2062

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

Upvotes: 1

Views: 3717

Answers (2)

Xelnor
Xelnor

Reputation: 3589

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")

Upvotes: 7

munsu
munsu

Reputation: 2062

I went with the approach below which might be useful to some:

user = factory.LazyFunction(lambda: UserProfileFactory().user)

That said, it's not documented if this is a legitimate way of using factories, so feel free to correct if this is wrong.

Upvotes: 1

Related Questions