pythondjangodjango-rest-frameworkfakerfactory-boy

Factory boy connect models to existing users


Im populating my database with dummy data, I have separate Profile, User, Picture model. How can connect them to use same users?

class UserFactory(DjangoModelFactory):

    class Meta:
        model = User

    email = factory.Faker('email')
    first_name = factory.Faker('first_name')
    birthday = factory.Faker('date_object')
    age = factory.Faker('pyint', min_value=18, max_value=100)
    is_staff = False
    is_active = True

class UserPhotoFactory(DjangoModelFactory):

    class Meta:
        model = UserPhoto

    user = factory.RelatedFactory(UserFactory) #????
    order = factory.Faker('pyint', min_value=0, max_value=4)
    url = factory.Faker(
        'random_element', elements=[x for x in ['https://picsum.photos/seed/picsum/200/300', 'https://picsum.photos/seed/pssss/200/300', 'https://picsum.photos/seed/picwum/200/300']]
    )

class ProfileFactory(DjangoModelFactory):

    class Meta:
        model = Profile
    
    user = factory.SubFactory(UserFactory)
    bio = factory.LazyAttribute(lambda o: FAKE.paragraph(nb_sentences=5, ext_word_list=['abc', 'def', 'ghi', 'jkl']))

In this case I'm calling in shell

ProfileFacotry.create_batch(10)

And that creates users and their corresponding profiles. Now I want to add UserPhoto to the mix that is related to USER via ForeignKey like this

class UserPhoto(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    order = models.PositiveIntegerField(null=True)
    url = models.CharField(max_length=220)

What I want to achieve is to get 10 users 10 profiles and let say 20 pictures 2 for each user


Solution

  • Rather than go via the subfactory of Profile, you can use FactoryBoy's reverse dependencies to create them for each user

    This would look something like:

    class UserFactory(DjangoModelFactory):
    
        class Meta:
            model = User
    
        email = factory.Faker('email')
        first_name = factory.Faker('first_name')
        birthday = factory.Faker('date_object')
        age = factory.Faker('pyint', min_value=18, max_value=100)
        is_staff = False
        is_active = True
    
        profile = factory.RelatedFactory(
            ProfileFactory,
            factory_related_name = 'profile',
            action=models.Profile.ACTION_CREATE,
        )
    
        image1 = factory.RelatedFactory(
            UserPhotoFactory,
            factory_related_name = 'user_photo',
            action=models.Profile.ACTION_CREATE,
        )
    
        image2 = factory.RelatedFactory(
            UserPhotoFactory,
            factory_related_name = 'user_photo',
            action=models.Profile.ACTION_CREATE,
        )