如何解决factory_boy子工厂调用中的CyclicDefinitionError?

时间:2020-07-21 10:11:52

标签: django factory-boy

我有以下型号

# 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

我希望能够创建ModelB具有ModelA的{​​{1}}对象。 尝试行TYPEB 导致错误:

factory.errors.CyclicDefinitionError:循环惰性属性定义 用于“类型”; ['type']

中找到的循环

此外,当我将ModelBFactory.create(type = ModelA.TYPEB)类中的type名称更改为例如Params具有:

model_type

失败并

AttributeError:参数'model_type'未知。

我如何实现我的目标?

2 个答案:

答案 0 :(得分:1)

编写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'),
    )

答案 1 :(得分:0)

我找到了解决方案。 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

我没有将ModelAFactory属性设置为LazyAttribute,而是不得不将whoel工厂设置为一个。