How can I set User Groups using factory_boy
Asked Answered
M

2

7

I am fairly new to Django. I am trying to set the groups field for User using factory_boy. The default User class has a field _groups. I tried setting that, but that is not helping.

class GroupFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Group

    name = Sequence(lambda n: "group_{0}".format(n))


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

    username = factory.Sequence(lambda n: "user_{0}".format(n))
    password = "test"
    first_name = u'ßhamra'
    last_name = u'ßhamra'
    _groups = factory.SubFactory(GroupFactory)


    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        """
        Override the default ``_create`` with our custom call.
        Due to internal behavior or create user create method that                forces is_staff kwarg


    """
    g = GroupFactory("abc")
    manager = cls._get_manager(model_class)
    is_staff = kwargs.pop('is_staff', None)
    user = manager.create_user(*args, **kwargs)


    if is_staff:
        user.is_staff = is_staff
        user.save()
    return user
Muskeg answered 6/2, 2015 at 14:11 Comment(0)
V
13

The code below utilizes the standard django groups. You have to use a factory boy post generation to add groups to the user.

Factories

import factory
import django.contrib.auth.models as auth_models
from django.contrib.auth.hashers import make_password

user_password = 'password'

class SubscribedGroupFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = auth_models.Group

    name = 'subscribed'

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = auth_models.User

    first_name = "Sophia"
    last_name = "Ball"
    username = "[email protected]"
    password = make_password(user_password)
    email = "[email protected]"
    is_active = True

    @factory.post_generation
    def groups(self, create, extracted, **kwargs):
        if not create:
            return

        if extracted:
            for group in extracted:
                self.groups.add(group)

Test

from app.factories import UserFactory, SubscribedGroupFactory, user_password
class TestCenterTest(TestCase):

    def test_test_center_redirect(self):
        user = UserFactory.create(groups=(SubscribedGroupFactory.create(),))
        self.client.login(username=user.email, password=user_password)
        response = self.client.get('/test-center/')
        self.assertEqual(302, response.status_code)
Vanda answered 31/3, 2016 at 14:5 Comment(0)
W
0

Since Group has a ManyToManyField relation to User, you cannot use SubFactory (which is only suited for a ForeignKey field): with a SubFactory, factory_boy will first create the Group then pass it to UserFactory which uses it as User.objects.create(_groups=Group). This won't work.

Take a look at the Recipes section of the documentation: http://factoryboy.readthedocs.org/en/latest/recipes.html#simple-manytomany

Here, the following code should work:

  class UserFactory(factory.django.DjangoModelFactory):
      # All other declarations here

      groups = factory.List([
          factory.RelatedFactory(GroupFactory),
      ])
Whoa answered 6/2, 2015 at 15:0 Comment(1)
Xelnor: I have not defined groups field explicitly in Users Model. I am getting the error 'groups' is an invalid keyword argument for this function . I have been stuck in this for very long now.Muskeg

© 2022 - 2024 — McMap. All rights reserved.