FactoryBoy creates a new object from SubFactory despite FACTORY_DJANGO_GET_OR_CREATE
See original GitHub issueI am using the setting FACTORY_DJANGO_GET_OR_CREATE
. But in some cases, 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 typed:
# 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)
Then:
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
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!
(I also asked this on StackOverflow here too.)
Issue Analytics
- State:
- Created 10 years ago
- Reactions:4
- Comments:11 (4 by maintainers)
Top GitHub Comments
Hi @rbarrois! I was working and suddenly I run into this issue. I’m glad that you already know whats going on. I leave here for you 2 questions.
Thanks in advanced Regards
Hello everyone,
I’ve just looked at how subfactories are called, and it appeared that any kwargs in the SubFactory call are passed to the factory (the first argument in that call)
So I tried with the following and it works just fine
And then several calls to RefundFactory all use the same BatchFile with id 122.
Seems like factory-boy also accepts
factory.SelfAttribute
calls inside those kwargs, like so,But then “…amount” must be a field on the upper object’s class, here Refund.
Hope this can help