【问题标题】:How to resolve CyclicDefinitionError in factory_boy SubFactory call?如何解决 factory_boy SubFactory 调用中的 CyclicDefinitionError?
【发布时间】:2020-07-21 19:14:55
【问题描述】:

我有以下型号

# 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

我希望能够使用 ModelATYPEB 创建 ModelB 对象。 试行ModelBFactory.create(type = ModelA.TYPEB) 导致错误:

factory.errors.CyclicDefinitionError:循环惰性属性定义 对于“类型”;在 ['type'] 中找到循环

此外,当我将 type 类中的 type 名称更改为例如model_type 有:

model_a = SubFactory(ModelAFactory, type = factory.LazyAttribute(lambda o: '%d' % o.model_type))

失败了

AttributeError:参数“model_type”未知。

我怎样才能实现我的目标?

【问题讨论】:

    标签: django factory-boy


    【解决方案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'),
        )
    

    【讨论】:

      【解决方案2】:

      我找到了解决方案。 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 而是将整个工厂作为一个。

      【讨论】:

      • 这个解决方案有点用,但是你会失去SubFactory的所有好处:共享策略(ModelBFactory.build / ModelBFactory.create),在调用时覆盖字段的能力(ModelBFactory(model_a__name='example') ) 等。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 2015-04-06
      • 2022-06-23
      • 2021-07-07
      • 1970-01-01
      相关资源
      最近更新 更多