# Common recipes

Note

Most recipes below take on Django model examples, but can also be used on their own.

## Dependent objects (ForeignKey)

When one attribute is actually a complex field (e.g a `ForeignKey` to another `Model`), use the `SubFactory` declaration:

    # models.py
    class User(models.Model):
        first_name = models.CharField()
        group = models.ForeignKey(Group)

    # factories.py
    import factory
    from . import models

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

        first_name = factory.Sequence(lambda n: "Agent %03d" % n)
        group = factory.SubFactory(GroupFactory)

### Choosing from a populated table

If the target of the `ForeignKey` should be chosen from a pre-populated table (e.g `django.contrib.contenttypes.models.ContentType`), simply use a `factory.Iterator` on the chosen queryset:

    import factory, factory.django
    from . import models

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

        language = factory.Iterator(models.Language.objects.all())

Here, `models.Language.objects.all()` won’t be evaluated until the first call to `UserFactory`; thus avoiding DB queries at import time.

## Reverse dependencies (reverse ForeignKey)

When a related object should be created upon object creation (e.g a reverse `ForeignKey` from another `Model`), use a `RelatedFactory` declaration:

    # models.py
    class User(models.Model):
        pass

    class UserLog(models.Model):
        user = models.ForeignKey(User)
        action = models.CharField()

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

        log = factory.RelatedFactory(UserLogFactory, 'user', action=models.UserLog.ACTION_CREATE)

When a `UserFactory` is instantiated, factory_boy will call `UserLogFactory(user=that_user, action=...)` just before returning the created `User`.

### Example: Django’s Profile

Django (<1.5) provided a mechanism to attach a `Profile` to a `User` instance, using a `OneToOneField` from the `Profile` to the `User`.

A typical way to create those profiles was to hook a post-save signal to the `User` model.

Prior to version 2.9, the solution to this was to override the `_generate()` method on the factory.

Since version 2.9, the `mute_signals()` decorator should be used:

    @factory.django.mute_signals(post_save)
    class ProfileFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = my_models.Profile

        title = 'Dr'
        # We pass in profile=None to prevent UserFactory from creating another profile
        # (this disables the RelatedFactory)
        user = factory.SubFactory('app.factories.UserFactory', profile=None)

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

        username = factory.Sequence(lambda n: "user_%d" % n)

        # We pass in 'user' to link the generated Profile to our just-generated User
        # This will call ProfileFactory(user=our_new_user), thus skipping the SubFactory.
        profile = factory.RelatedFactory(ProfileFactory, 'user')

    >>> u = UserFactory(profile__title=u"Lord")
    >>> u.get_profile().title
    u"Lord"

Such behaviour can be extended to other situations where a signal interferes with factory_boy related factories.

Any factories that call these classes with `SubFactory` will also need to be decorated in the same manner.

Note

When any `RelatedFactory` or `post_generation` attribute is defined on the `DjangoModelFactory` subclass, a second `save()` is performed after the call to `_create()`.

Code working with signals should thus use the `mute_signals()` decorator

## Simple Many-to-many relationship

Building the adequate link between two models depends heavily on the use case; factory_boy doesn’t provide a “all in one tools” as for `SubFactory` or `RelatedFactory`, users will have to craft their own depending on the model.

The base building block for this feature is the `post_generation` hook:

    # models.py
    class Group(models.Model):
        name = models.CharField()

    class User(models.Model):
        name = models.CharField()
        groups = models.ManyToManyField(Group)

    # factories.py
    class GroupFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.Group

        name = factory.Sequence(lambda n: "Group #%s" % n)

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

        name = "John Doe"

        @factory.post_generation
        def groups(self, create, extracted, **kwargs):
            if not create:
                # Simple build, do nothing.
                return

            if extracted:
                # A list of groups were passed in, use them
                for group in extracted:
                    self.groups.add(group)

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.

## Many-to-many relation with a ‘through’

If only one link is required, this can be simply performed with a `RelatedFactory`. If more links are needed, simply add more `RelatedFactory` declarations:

    # models.py
    class User(models.Model):
        name = models.CharField()

    class Group(models.Model):
        name = models.CharField()
        members = models.ManyToManyField(User, through='GroupLevel')

    class GroupLevel(models.Model):
        user = models.ForeignKey(User)
        group = models.ForeignKey(Group)
        rank = models.IntegerField()

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

        name = "John Doe"

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

        name = "Admins"

    class GroupLevelFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.GroupLevel

        user = factory.SubFactory(UserFactory)
        group = factory.SubFactory(GroupFactory)
        rank = 1

    class UserWithGroupFactory(UserFactory):
        membership = factory.RelatedFactory(GroupLevelFactory, 'user')

    class UserWith2GroupsFactory(UserFactory):
        membership1 = factory.RelatedFactory(GroupLevelFactory, 'user', group__name='Group1')
        membership2 = factory.RelatedFactory(GroupLevelFactory, 'user', group__name='Group2')

Whenever the `UserWithGroupFactory` is called, it will, as a post-generation hook, call the `GroupLevelFactory`, passing the generated user as a `user` field:

1. `UserWithGroupFactory()` generates a `User` instance, `obj`

2. It calls `GroupLevelFactory(user=obj)`

3. It returns `obj`

When using the `UserWith2GroupsFactory`, that behavior becomes:

1. `UserWith2GroupsFactory()` generates a `User` instance, `obj`

2. It calls `GroupLevelFactory(user=obj, group__name='Group1')`

3. It calls `GroupLevelFactory(user=obj, group__name='Group2')`

4. It returns `obj`

## Copying fields to a SubFactory

When a field of a related class should match one of the container:

    # models.py
    class Country(models.Model):
        name = models.CharField()
        lang = models.CharField()

    class User(models.Model):
        name = models.CharField()
        lang = models.CharField()
        country = models.ForeignKey(Country)

    class Company(models.Model):
        name = models.CharField()
        owner = models.ForeignKey(User)
        country = models.ForeignKey(Country)

Here, we want:

- The User to have the lang of its country (`factory.SelfAttribute('country.lang')`)

- The Company owner to live in the country of the company (`factory.SelfAttribute('..country')`)

    # factories.py
    class CountryFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.Country

        name = factory.Iterator(["France", "Italy", "Spain"])
        lang = factory.Iterator(['fr', 'it', 'es'])

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

        name = "John"
        lang = factory.SelfAttribute('country.lang')
        country = factory.SubFactory(CountryFactory)

    class CompanyFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.Company

        name = "ACME, Inc."
        country = factory.SubFactory(CountryFactory)
        owner = factory.SubFactory(UserFactory, country=factory.SelfAttribute('..country'))

If the value of a field on the child factory is indirectly derived from a field on the parent factory, you will need to use LazyAttribute and poke the “factory_parent” attribute.

This time, we want the company owner to live in a country neighboring the country of the company:

    class CompanyFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.Company

        name = "ACME, Inc."
        country = factory.SubFactory(CountryFactory)
        owner = factory.SubFactory(UserFactory,
            country=factory.LazyAttribute(lambda o: get_random_neighbor(o.factory_parent.country)))

## Custom manager methods

Sometimes you need a factory to call a specific manager method other then the default `Model.objects.create()` method:

    class UserFactory(factory.DjangoModelFactory):
        class Meta:
            model = UserenaSignup

        username = "l7d8s"
        email = "my_name@example.com"
        password = "my_password"

        @classmethod
        def _create(cls, model_class, *args, **kwargs):
            """Override the default ``_create`` with our custom call."""
            manager = cls._get_manager(model_class)
            # The default would use ``manager.create(*args, **kwargs)``
            return manager.create_user(*args, **kwargs)

## Forcing the sequence counter

A common pattern with factory_boy is to use a `factory.Sequence` declaration to provide varying values to attributes declared as unique.

However, it is sometimes useful to force a given value to the counter, for instance to ensure that tests are properly reproductible.

factory_boy provides a few hooks for this:

Forcing the value on a per-call basis

  In order to force the counter for a specific `Factory` instantiation, just pass the value in the `__sequence=42` parameter:

      class AccountFactory(factory.Factory):
          class Meta:
              model = Account
          uid = factory.Sequence(lambda n: n)
          name = "Test"

      >>> obj1 = AccountFactory(name="John Doe", __sequence=10)
      >>> obj1.uid  # Taken from the __sequence counter
      10
      >>> obj2 = AccountFactory(name="Jane Doe")
      >>> obj2.uid  # The base sequence counter hasn't changed
      1

Resetting the counter globally

  If all calls for a factory must start from a deterministic number, use `factory.Factory.reset_sequence()`; this will reset the counter to its initial value (as defined by `factory.Factory._setup_next_sequence()`).

      >>> AccountFactory().uid
      1
      >>> AccountFactory().uid
      2
      >>> AccountFactory.reset_sequence()
      >>> AccountFactory().uid  # Reset to the initial value
      1
      >>> AccountFactory().uid
      2

  It is also possible to reset the counter to a specific value:

      >>> AccountFactory.reset_sequence(10)
      >>> AccountFactory().uid
      10
      >>> AccountFactory().uid
      11

  This recipe is most useful in a `TestCase`’s `setUp()` method.

Forcing the initial value for all projects

  The sequence counter of a `Factory` can also be set automatically upon the first call through the `_setup_next_sequence()` method; this helps when the objects’s attributes mustn’t conflict with pre-existing data.

  A typical example is to ensure that running a Python script twice will create non-conflicting objects, by setting up the counter to “max used value plus one”:

      class AccountFactory(factory.django.DjangoModelFactory):
          class Meta:
              model = models.Account

          @classmethod
          def _setup_next_sequence(cls):
              try:
                  return models.Accounts.objects.latest('uid').uid + 1
              except models.Account.DoesNotExist:
                  return 1

      >>> Account.objects.create(uid=42, name="Blah")
      >>> AccountFactory.create()  # Sets up the account number based on the latest uid
      <Account uid=43, name=Test>

## Converting a factory’s output to a dict

In order to inject some data to, say, a REST API, it can be useful to fetch the factory’s data as a dict.

Internally, a factory will:

1. Merge declarations and overrides from all sources (class definition, call parameters, …)

2. Resolve them into a dict

3. Pass that dict as keyword arguments to the model’s `build` / `create` function

In order to get a dict, we’ll just have to swap the model; the easiest way is to use `factory.build()`:

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

        first_name = factory.Sequence(lambda n: "Agent %03d" % n)
        username = factory.Faker('username')

    >>> factory.build(dict, FACTORY_CLASS=UserFactory)
    {'first_name': "Agent 001", 'username': 'john_doe'}

## Django models with GenericForeignKeys

For model which uses GenericForeignKey

    from __future__ import unicode_literals

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes.fields import GenericForeignKey

    class TaggedItem(models.Model):
        """Example GenericForeinKey model from django docs"""
        tag = models.SlugField()
        content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
        object_id = models.PositiveIntegerField()
        content_object = GenericForeignKey('content_type', 'object_id')

        def __str__(self):  # __unicode__ on Python 2
            return self.tag

We can create factories like this:

    import factory
    from django.contrib.auth.models import User, Group
    from django.contrib.contenttypes.models import ContentType

    from .models import TaggedItem

    class UserFactory(factory.DjangoModelFactory):
        first_name = 'Adam'

        class Meta:
            model = User

    class GroupFactory(factory.DjangoModelFactory):
        name = 'group'

        class Meta:
            model = Group

    class TaggedItemFactory(factory.DjangoModelFactory):
        object_id = factory.SelfAttribute('content_object.id')
        content_type = factory.LazyAttribute(
            lambda o: ContentType.objects.get_for_model(o.content_object))

        class Meta:
            exclude = ['content_object']
            abstract = True

    class TaggedUserFactory(TaggedItemFactory):
        content_object = factory.SubFactory(UserFactory)

        class Meta:
            model = TaggedItem

    class TaggedGroupFactory(TaggedItemFactory):
        content_object = factory.SubFactory(GroupFactory)

        class Meta:
            model = TaggedItem