如何解决 factory_boy SubFactory 调用中的 CyclicDefinitionError?
How to resolve CyclicDefinitionError in factory_boy SubFactory call?
我有以下型号
# in ModelA_App/models.py
class ModelA(models.Model):
TYPEA = 1
TYPEB = 2
TYPE_CHOICES = (
(TYPEA, 'TypeA'),
(TYPEB, 'TypeB')
)
type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES)
name - models.CharField(max_length = 100)
#in ModelB_App/models.py
from ModelA_App.models import ModelA
class ModelB(models.Model):
label = models.TextFiled()
model_a = models.OneToOneField(ModelA, on_delete=models.CASCADE)
我有以下工厂:
#in ModelA_App/factories.py
class ModelAFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelA
name = factory.Faker('word')
type = ModelA.TYPEA
#in ModelB_App/factories.py
from ModelA_App.models import ModelA
from ModelA_App.factories import ModelAFactory
class ModelBFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelB
label = factory.Faker('text')
model_a = SubFactory(ModelAFactory, type = factory.LazyAttribute(lambda o: '%d' % o.type))
class Params:
type = ModelA.TYPEA
我希望能够创建具有 ModelA
和 TYPEB
的 ModelB
对象。
尝试行 ModelBFactory.create(type = ModelA.TYPEB)
结果错误:
factory.errors.CyclicDefinitionError: Cyclic lazy attribute definition
for 'type'; cycle found in ['type']
此外,当我将 Params
class 中的 type
名称更改为例如model_type
拥有:
model_a = SubFactory(ModelAFactory, type = factory.LazyAttribute(lambda o: '%d' % o.model_type))
它失败了
AttributeError: The parameter 'model_type' is unknown.
我怎样才能实现我的目标?
我找到了解决方案。 ModelBFactory
应该是这样的:
#in ModelB_App/factories.py
from ModelA_App.models import ModelA
from ModelA_App.factories import ModelAFactory
class ModelBFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelB
label = factory.Faker('text')
model_a = factory.LazyAttribute(lambda o: ModelAFactory(type = o.type))
class Params:
type = ModelA.TYPEA
我不得不将 whoel 工厂作为一个属性,而不是将 ModelAFactory
属性作为一个 LazyAttribute
。
当您编写 SubFactory
时,您提供的附加定义将锚定到该子工厂。你所写的相当于:
class SubModelAFactory(ModelAFactory):
class Meta:
# Not required - implied by class inheritance
model = models.ModelA
type = factory.LazyAttribute(lambda o: '%d' % o.type)
class ModelBFactory(factory.django.DjangoModelFactory):
...
model_a = factory.SubFactory(SubModelFactory)
相反,您应该“上升”一个级别,如 the SelfAttribute
docs:
中所述
class ModelBFactory(factory.django.DjangoModelFactory):
...
model_a = factory.SubFactory(
SubModelFactory,
type=factory.LazyAttribute(lambda o: '%d' % o.factory_parent.type),
# If the value can be passed without conversion, use:
type=factory.SelfAttribute('..type'),
)
我有以下型号
# in ModelA_App/models.py
class ModelA(models.Model):
TYPEA = 1
TYPEB = 2
TYPE_CHOICES = (
(TYPEA, 'TypeA'),
(TYPEB, 'TypeB')
)
type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES)
name - models.CharField(max_length = 100)
#in ModelB_App/models.py
from ModelA_App.models import ModelA
class ModelB(models.Model):
label = models.TextFiled()
model_a = models.OneToOneField(ModelA, on_delete=models.CASCADE)
我有以下工厂:
#in ModelA_App/factories.py
class ModelAFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelA
name = factory.Faker('word')
type = ModelA.TYPEA
#in ModelB_App/factories.py
from ModelA_App.models import ModelA
from ModelA_App.factories import ModelAFactory
class ModelBFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelB
label = factory.Faker('text')
model_a = SubFactory(ModelAFactory, type = factory.LazyAttribute(lambda o: '%d' % o.type))
class Params:
type = ModelA.TYPEA
我希望能够创建具有 ModelA
和 TYPEB
的 ModelB
对象。
尝试行 ModelBFactory.create(type = ModelA.TYPEB)
结果错误:
factory.errors.CyclicDefinitionError: Cyclic lazy attribute definition for 'type'; cycle found in ['type']
此外,当我将 Params
class 中的 type
名称更改为例如model_type
拥有:
model_a = SubFactory(ModelAFactory, type = factory.LazyAttribute(lambda o: '%d' % o.model_type))
它失败了
AttributeError: The parameter 'model_type' is unknown.
我怎样才能实现我的目标?
我找到了解决方案。 ModelBFactory
应该是这样的:
#in ModelB_App/factories.py
from ModelA_App.models import ModelA
from ModelA_App.factories import ModelAFactory
class ModelBFactory(factory.django.DjangoModelFactory):
class Meta:
model = ModelB
label = factory.Faker('text')
model_a = factory.LazyAttribute(lambda o: ModelAFactory(type = o.type))
class Params:
type = ModelA.TYPEA
我不得不将 whoel 工厂作为一个属性,而不是将 ModelAFactory
属性作为一个 LazyAttribute
。
当您编写 SubFactory
时,您提供的附加定义将锚定到该子工厂。你所写的相当于:
class SubModelAFactory(ModelAFactory):
class Meta:
# Not required - implied by class inheritance
model = models.ModelA
type = factory.LazyAttribute(lambda o: '%d' % o.type)
class ModelBFactory(factory.django.DjangoModelFactory):
...
model_a = factory.SubFactory(SubModelFactory)
相反,您应该“上升”一个级别,如 the SelfAttribute
docs:
class ModelBFactory(factory.django.DjangoModelFactory):
...
model_a = factory.SubFactory(
SubModelFactory,
type=factory.LazyAttribute(lambda o: '%d' % o.factory_parent.type),
# If the value can be passed without conversion, use:
type=factory.SelfAttribute('..type'),
)