【问题标题】:Factory Boy subfactory over 'self'工厂男孩子工厂超过“自我”
【发布时间】:2016-02-05 15:32:55
【问题描述】:

有谁知道如何根据这个models.py在factoryboy中创建工厂

class Halte(models.Model):

    koppel_halte1 = models.ForeignKey('self',
                                  related_name='koppel_halteA',
                                  verbose_name="Koppel Halte",
                                  help_text="geef hier een gekoppelde halte aan",
                                  null=True, blank=True)

    koppel_halte2 = models.ForeignKey('self',
                                  related_name='koppel_halteB',
                                  verbose_name="Koppel Halte",
                                  help_text="geef hier een gekoppelde halte aan",
                                  null=True, blank=True)

注意到“自我”了吗? (是的,这种类型的关系是必要的。)

我在 FactoryBoy 中尝试了几件事(SubFactory、RelatedFactory、SelfAtribute、PostGeneration),但我无法让它工作。

在 factory.py 中的尝试之一

class HalteFactoryA(factory.DjangoModelFactory):
    class Meta:
        model = models.Halte


class HalteFactoryB(factory.DjangoModelFactory):
    class Meta:
        model = models.Halte


class HalteFactory(factory.DjangoModelFactory):
    class Meta:
        model = models.Halte
    # todo: how to do this?? (see models.Halte)
    koppel_halte1 = factory.RelatedFactory(HalteFactoryA)
    koppel_halte2 = factory.RelatedFactory(HalteFactoryB)

有什么建议吗?

谢谢。

【问题讨论】:

    标签: python django factory-boy


    【解决方案1】:

    @bakkal 基本正确,但一个重要的缺失因素是必须指定目标递归深度,如本期所述: https://github.com/rbarrois/factory_boy/issues/173

    # myproj/myapp/factories.py
    class MyModelFactory(factory.Factory):
        class Meta:
            model = models.MyModel
        parent = factory.SubFactory('myapp.factories.MyModelFactory')
    

    然后需要添加递归最大深度,否则会出现无限深度达到错误(如 cmets 中的@Sjoerd van Poelgeest 所述):

    m = MyModelFactory(parent__parent__parent__parent=None)
    

    在这种情况下,我们允许创建深度 3,并且最后一个将有一个 null 父级。

    【讨论】:

      【解决方案2】:

      模型 FK 中的完全限定模型名称

      为了让工具更容易自省模型,请使用完全限定的模型名称,而不是 'self',

      koppel_halte1 = models.ForeignKey('yourapp.Halte', ...)
      koppel_halte2 = models.ForeignKey('yourapp.Halte', ...)
      

      注意它是一个字符串 'yourapp.Halte' 而不是 yourapp.Halte

      子工厂中的完全限定工厂名称

      如果您坚持在模型中使用'self',您可以在SubFactory 中使用完全限定的模型名称

      # yourapp/factories.py
      
      class HalteFactory(factory.Factory):
          class Meta:
              model = yourapp.Halte
      
          koppel_halte1 = factory.SubFactory('yourapp.factories.HalteFactory')
          koppel_halte2 = factory.SubFactory('yourapp.factories.HalteFactory')
      

      【讨论】:

      • 这可能有效,但如何从中创建工厂男孩实例。我会自己尝试更新问题以澄清
      • 我可能在您发表评论之前已经更新了答案,如果您遇到问题,请注意 sn-p 和错误,我们可以讨论
      • hmm.. 刚刚以最大递归深度(无限循环)使所有测试崩溃......我现在要走了。我下周再试一次。
      • 单独这样做会导致最大递归深度误差,根据这个问题(github.com/rbarrois/factory_boy/issues/173),需要创建一个截止目标深度。
      【解决方案3】:

      我未能使用 Factory Boy 修复它,但老式的设置确实有效。

      那我会(不情愿地)使用标准。

          class ModelHalteSelfTests(TestCase):
          def setUp(self):
              self.lijn1 = Lijn.objects.create(id=1, nummer=1, techniek=GlobalWaardes.TECHNIEK_BUS)
              self.lijn2 = Lijn.objects.create(id=2, nummer=2, techniek=GlobalWaardes.TECHNIEK_TRAM)
      
              self.halte1 = Halte.objects.create(id=1, nummer=100, aantal_vitrinekasten=2, aantal_hpkasten=0)
              self.halte2 = Halte.objects.create(id=2, nummer=200, aantal_vitrinekasten=1, aantal_hpkasten=1)
              self.halte3 = Halte.objects.create(id=3, nummer=300, aantal_vitrinekasten=0, aantal_hpkasten=3)
              self.halte4 = Halte.objects.create(id=4, koppel_halte1=self.halte1, koppel_halte2=self.halte2)
      
              self.halteregel1 = Halteregel.objects.create(id=1, lijn=self.lijn1, halte=self.halte1, volgorde=10)
              self.halteregel2 = Halteregel.objects.create(id=2, lijn=self.lijn1, halte=self.halte2, volgorde=20)
              self.halteregel3 = Halteregel.objects.create(id=3, lijn=self.lijn2, halte=self.halte2, volgorde=20)
              self.halteregel4 = Halteregel.objects.create(id=4, lijn=self.lijn2, halte=self.halte3, volgorde=10)
      
          def test_lijst_halteregels(self):
              self.assertEqual(self.halte1.lijst_halteregels(), [self.halteregel1])
              self.assertEqual(self.halte2.lijst_halteregels(), [self.halteregel2, self.halteregel3])
              self.assertEqual(self.halte3.lijst_halteregels(), [self.halteregel4])
              self.assertEqual(self.halte4.lijst_halteregels(), [self.halteregel1, self.halteregel2, self.halteregel3])
      

      【讨论】:

        猜你喜欢
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-29
        相关资源
        最近更新 更多