Django: one-to-one field with factory_boy: UNIQUE constraint failed
Asked Answered
F

2

13

I'm trying to make factories for these models with factory_boy:

class Course(models.Model):
    group = models.OneToOneField(Group)
    title = models.CharField(max_length=1024)


class CourseInfo(models.Model):
    course = models.OneToOneField(Course, related_name='info')
    starttime = models.TimeField(null=True, blank=True)
    endtime = models.TimeField(null=True, blank=True)

Here are my factories:

class CourseInfoFactory(factory.DjangoModelFactory):
    class Meta:
        model = CourseInfo

    course = factory.SubFactory('courseaffils.tests.factories.CourseFactory')
    starttime = time(hour=4)
    endtime = time(hour=6)


class CourseFactory(factory.DjangoModelFactory):
    class Meta:
        model = Course

    title = factory.Sequence(lambda n: 'Example Course %d' % n)
    group = factory.SubFactory(GroupFactory)
    info = factory.RelatedFactory(CourseInfoFactory, 'course')

Now, when I call CourseFactory() or CourseInfoFactory() I get an IntegrityError:

IntegrityError: UNIQUE constraint failed: courseaffils_courseinfo.course_id

What's wrong with my factories? How can I fix this problem?

If I instead do course = factory.RelatedFactory('courseaffils.tests.factories.CourseFactory') on the CourseInfoFactory, I get this error, as expected:

IntegrityError: NOT NULL constraint failed: courseaffils_courseinfo.course_id

If you need more details, here's the actual code I'm working with:

https://github.com/ccnmtl/django_courseaffils/blob/master/courseaffils/models.py

Faulty answered 16/3, 2016 at 15:13 Comment(0)
F
2

The problem was that CourseFactory() already creates a CourseInfo object. I've resolved this by just removing the info = factory.RelatedFactory(CourseInfoFactory, 'course') line, and now the CourseInfoFactory is unnecessary - I can test CourseInfo by getting the created object at course.info.

Faulty answered 16/3, 2016 at 20:0 Comment(0)
C
15

Just add the django_get_or_create in the Meta class of your CourseInfoFactory:

class Meta:
    django_get_or_create = ('group',)

This solution avoids the problem of a unique constraint in your field, and creates it if exists.

You could check here: https://github.com/FactoryBoy/factory_boy/blob/v2.5.2/factory/django.py#L133-L139

Calbert answered 17/8, 2016 at 22:35 Comment(2)
This answer isn't quite specific enough. Can you think of additional information you can provide to make it clearer/better?Mccarver
please check if there is something missingCalbert
F
2

The problem was that CourseFactory() already creates a CourseInfo object. I've resolved this by just removing the info = factory.RelatedFactory(CourseInfoFactory, 'course') line, and now the CourseInfoFactory is unnecessary - I can test CourseInfo by getting the created object at course.info.

Faulty answered 16/3, 2016 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.