Search code examples
pythondjangofakerfactory-boy

Cannot populate dummy data against ManyToManyField


I am trying to create test data for a Django model in my project using factoryboy. The data is being generated through Faker except one field, that is a ManyToManyField; a many to many relationship with another builtin model from django.contrib.auth.model named group.

class Voucher(models.Model):
    code = models.CharField(max_length=20, null=True, blank=True, unique=True)
    is_enabled = models.BooleanField('enable voucher', default=True, help_text='A soft delete mechanism for the voucher.')
    start_date = models.DateTimeField(null=True, blank=True)
    end_date = models.DateTimeField(null=True, blank=True)
    member_roles = models.ManyToManyField(to=Group, related_name='member_roles')

    def __str__(self):
        return "{}".format(self.code)

    class Meta:
        verbose_name = 'Voucher'
        verbose_name_plural = 'Vouchers'

This is my model and this is the factory I created to generate dummy data:

class VoucherFactory(django.DjangoModelFactory):
    class Meta:
        model = 'app.Voucher'

    code = Faker('first_name')
    is_enabled = fuzzy.FuzzyChoice([True, False])
    start_date = fuzzy.FuzzyDateTime(datetime.datetime.now(pytz.utc))
    end_date = fuzzy.FuzzyDateTime(datetime.datetime.now(pytz.utc))

    @factory.post_generation
    def member_roles(self, create, extracted, **kwargs):
        if not create:
            return
        if extracted:
            for member_role in extracted:
                self.member_roles.add(member_role)

The data gets filled successfully except voucher_member_roles table created against this many to many relationship in Voucher model. I want this table to get populated also.

What I am missing?


Solution

  • You need to pass in the member_roles when making the voucher factory. For example:

    VoucherFactory.create(member_roles=[member_role1, member_role2])
    

    See http://factoryboy.readthedocs.io/en/latest/recipes.html#simple-many-to-many-relationship where it states:

    When calling UserFactory() or UserFactory.build(), no group binding will be created. But when UserFactory.create(groups=(group1, group2, group3)) is called, the groups declaration will add passed in groups to the set of groups for the user.