Search code examples
pythondjangodatabasefactory-boy

In Django Factory Boy, is it possible to specify custom FactoryOptions for a certain instance?


I'm writing unit tests for a Django app which use factory_boy test fixtures. In some cases, one fixture might try to create an object that was already created by another fixture, which leads to error messages similar to the following:

django.db.utils.IntegrityError: duplicate key value violates unique constraint "lucy_web_sessiontype_title_c207e4f8_uniq"
DETAIL:  Key (title)=(Postpartum Doula Support) already exists.

To avoid this, my first inclination is to write a try..except block, like so:

try:
    SessionTypeFactory(title='Welcome')
except psycopg2.IntegrityError as e:
    pass

However, it seems like it would be more elegant to use the django_get_or_create option described at http://factoryboy.readthedocs.io/en/latest/orms.html#factory.django.DjangoOptions.django_get_or_create.

However, as far as I can tell from http://factoryboy.readthedocs.io/en/latest/reference.html#factory.FactoryOptions, options specifie in the factory's Meta class will apply to all instances, whereas I would only like it to only apply to this instance. Is it possible to specify these options in the constructor?


Solution

  • The doc is slightly misleading. What is documented in the FactoryOptions section is the list of options available in the class Meta part.

    In your case, you could go with the following code sample:

    class SessionTypeFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.SessionType
            django_get_or_create = ['title']
    
        # your fields here
    

    This will perform a SessionType.objects.get_or_create(title=fields.pop('title'), defaults=fields) every time you create an instance. Since you have a unique condition on the title field, you can safely put that behavior in place at the SessionTypeFactory level.