# 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()` is a `QuerySet` and will only hit the database when `factory_boy` starts iterating on it, i.e on 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,
            factory_related_name='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 `factory.Factory._generate` method on the factory.

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

    from django.db.models.signals import post_save

    @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, factory_related_name='user')

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

Such behavior 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 or not extracted:
                # Simple build, or nothing to add, do nothing.
                return

            # Add the iterable of groups using bulk addition
            self.groups.add(*extracted)

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.

For SQLAlchemy, change `self.groups.add(group)` in the above example to `self.groups.append(group)`.

## 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,
            factory_related_name='user',
        )

    class UserWith2GroupsFactory(UserFactory):
        membership1 = factory.RelatedFactory(
            GroupLevelFactory,
            factory_related_name='user',
            group__name='Group1',
        )
        membership2 = factory.RelatedFactory(
            GroupLevelFactory,
            factory_related_name='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 than the default `Model.objects.create()` method:

    class UserFactory(factory.django.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 reproducible.

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’ attributes mustn’t conflict with preexisting 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>

## Using reproducible randomness

Although using random values is great, it can provoke test flakiness. factory_boy provides a few helpers for this.

Note

Those methods will seed the random engine used in both `factory.Faker` and `factory.fuzzy` objects.

Seeding the random engine

  The simplest way to manage randomness is to push a selected seed when starting tests:

      import factory.random
      # Pass in any value
      factory.random.reseed_random('my awesome project')

Reproducing unseeded tests

  A project might choose not to use an explicit random seed (for better fuzzing), but still wishes to have reproducible tests.

  For such cases, use a combination of `factory.random.get_random_state()` and `factory.random.set_random_state()`.

  Since the random state structure is implementation-specific, we recommend passing it around as a base64-encoded pickle dump.

      class MyTestRunner:

          def setup_test_environment(self):
              state = os.environ.get('TEST_RANDOM_STATE')
              if state:
                  try:
                      decoded_state = pickle.loads(base64.b64decode(state.encode('ascii')))
                  except ValueError:
                      decoded_state = None
              if decoded_state:
                  factory.random.set_random_state(decoded_state)
              else:
                  encoded_state = base64.b64encode(pickle.dumps(factory.random.get_random_state()))
                  print("Current random state: %s" % encoded_state.decode('ascii'))
              super().setup_test_environment()

## 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)  # Agent 000, Agent 001, Agent 002
        username = factory.Faker('user_name')

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

## Fuzzying Django model field choices

When defining a `FuzzyChoice` you can reuse the same choice list from the model field descriptor.

Use the `getter` kwarg to select the first element from each choice tuple.

    class UserFactory(factory.Factory):
        class Meta:
            model = User

        # CATEGORY_CHOICES is a list of (key, title) tuples
        category = factory.fuzzy.FuzzyChoice(User.CATEGORY_CHOICES, getter=lambda c: c[0])

## Django models with GenericForeignKeys

For model which uses GenericForeignKey

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

    class TaggedItem(models.Model):
        """Example GenericForeignKey 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):
            return self.tag

We can create factories like this:

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

    import factory.django

    from .models import TaggedItem

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

        class Meta:
            model = User

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

        class Meta:
            model = Group

    class TaggedItemFactory(factory.django.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