Multiple fields not supported in django_get_or_create
See original GitHub issueI am currently using factory_boy with faker to generate test data for my django application. The model that I am currently testing looks like the following;
class Thing(models.Model):
name = models.CharField(max_length=50)
code = models.CharField(max_length=20, unique=True)
short_code = models.CharField(max_length=5, unique=True)
My factory looks like this;
class ThingFactory(factory.django.DjangoModelFactory)
class Meta:
model = app.models.Thing
django_get_or_create = ('code', 'short_code')
name = factory.lazy_attribute(lambda x: faker.company())
code = factory.sequence(lambda n: 'thing-code-%05d' % n)
short_code = factory.sequence(lambda n: '%05d' % n)
and my test to verify that this is functioning properly is;
def test_thing_code(self):
ThingFactory.create(code="test")
things = Thing.objects.all()
assert_equal(len(things), 1)
thing = Thing.objects.get(code="test")
ThingFactory.create(short_code=thing.short_code)
ThingFactory.create(code="test")
things = Clinic.objects.all()
assert_equal(len(things), 1)
The expected behaviour of this test is that when I run a create using the existing short_code, I should instead get the same object that already exists. Additionally, when I attempt to create a new object using the same code as the first line, I should also get the same object. When I execute this, I receive the following error message:
test_thing_code ... ERROR
======================================================================
ERROR: test_thing_code
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/app/test/tests.py", line 109, in test_thing_code
ThingFactory.create(short_code=thing.short_code)
File "/home/factory_boy/factory/base.py", line 559, in create
return cls._generate(True, attrs)
File "/home/factory_boy/factory/django.py", line 288, in wrapped_generate
return generate_method(*args, **kwargs)
File "/home/factory_boy/factory/base.py", line 484, in _generate
obj = cls._prepare(create, **attrs)
File "/home/factory_boy/factory/base.py", line 459, in _prepare
return cls._create(model_class, *args, **kwargs)
File "/home/factory_boy/factory/django.py", line 147, in _create
return cls._get_or_create(model_class, *args, **kwargs)
File "/home/factory_boy/factory/django.py", line 138, in _get_or_create
obj, _created = manager.get_or_create(*args, **key_fields)
File "/home/django/django/db/models/manager.py", line 134, in get_or_create
return self.get_query_set().get_or_create(**kwargs)
File "/home/django/django/db/models/query.py", line 452, in get_or_create
obj.save(force_insert=True, using=self.db)
File "/home/django/django/utils/functional.py", line 11, in _curried
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
File "/home/app/models.py", line 415, in capture_user_on_save
output = old_save(self, *args, **kwargs)
File "/home/app/models.py", line 264, in save
super(Thing, self).save(*args, **kwargs)
File "/home/django/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/home/django/django/db/models/base.py", line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/home/django/django/db/models/manager.py", line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/home/django/django/db/models/query.py", line 1593, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/django/django/db/models/sql/compiler.py", line 912, in execute_sql
cursor.execute(sql, params)
File "/home/django/django/db/backends/postgresql_psycopg2/base.py", line 52, in execute
return self.cursor.execute(query, args)
IntegrityError: duplicate key value violates unique constraint "app_thing_short_code_key"
DETAIL: Key (short_code)=(000) already exists.
This error was received using factory_boy 2.5.2 and Django 1.4.20 final
If I change the order in the django_get_or_create attribute, whichever one is listed second is the test that causes the database error.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:4
- Comments:11 (4 by maintainers)
Top GitHub Comments
I just recently started using factory boy and also encountered this issue. It’s basically impossible to create objects reliably if there is more than one unique field on the model. Most of my models have more than one unique in them. I don’t even want to know what kind of troubles I would get into if I had a unique_together constraint. Sad to see this issue is years old with little to no progress.
Any updates? It’s really crucial for the majority of users to have it implemented, myself included.