I have just started using factory boy with Django. It has a setting FACTORY_DJANGO_GET_OR_CREATE
that means it won't create a new object if one already exists. But when I ask for an existing object with an existing SubFactory
object, it creates an unused object despite this setting.
For example, in a brand new project, I tried:
# models.py
from django.db import models
class A(models.Model):
name = models.CharField(max_length=10)
class B(models.Model):
name = models.CharField(max_length=10)
a = models.ForeignKey(A)
And
# factories.py
import factory
from . import models
class AFactory(factory.DjangoModelFactory):
FACTORY_FOR = models.A
FACTORY_DJANGO_GET_OR_CREATE = ('name',)
name = factory.Sequence(lambda n: 'A-{0}'.format(n))
class BFactory(factory.DjangoModelFactory):
FACTORY_FOR = models.B
FACTORY_DJANGO_GET_OR_CREATE = ('name',)
name = factory.Sequence(lambda n: 'B-{0}'.format(n))
a = factory.SubFactory(AFactory)
Now:
from factories import *
a = AFactory(name="Apple")
models.A.objects.all()
# one object
b = BFactory(a__name="Apple", name="Beetle")
models.B.objects.all()
models.A.objects.all()
# one A object, one B object
b = BFactory(name="Beetle")
models.B.objects.all()
models.A.objects.all()
# still one B object, but now a new, unused A object too
Then the final call to BFactory
has brought into being a new object of class A
, even though the B
object with name Beetle already exists (and is not re-created). Why, and how do I stop this new A object being created?
(I know I can get around this by calling instead:
b = BFactory(name="Beetle", a__name="Apple")
but in my actual use case, I have several dependencies and levels of hierarchy, and it's messy to supply extra redundant parameters this way - and I can't seem to get the right combination of parameters.)
Thanks!
The above is a problem when I also have a class C that has a foreign key to B. When I created a new CFactory
object like so:
c = CFactory(name="Cat", b__name="Beetle")
it also creates a new unused A
object.
I have found the solution to this is simple: instead, make the new CFactory
object like this:
c = CFactory(name="Cat", b=b)
where b
is either a B
object or a BFactory
object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With