django 抽象模型中自引用字段的工厂男孩字段

问题描述 投票:0回答:1
class BaseOrganization(
    OrganizationModelMixin, TimeStampedModel, OrganizationWidgetsMixin
):
    name = models.CharField(max_length=255, verbose_name="Nomlanishi", null=True)
    juridical_address = models.CharField(
        max_length=150, verbose_name="Yuridik manzili", null=True, blank=True
    )
    phone_number = models.CharField(
        max_length=150,
        verbose_name="Telefon raqami",
        null=True,
        blank=True,
        validators=[phone_regex],
    )
    parent = models.ForeignKey(
        "self",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="%(class)s_children",
        verbose_name="Yuqori tashkilot",
    )


    class Meta:
        abstract = True

class BaseOrganizationFactory(factory.django.DjangoModelFactory):

    """Base organization factory"""
    name = factory.Faker("company")
    juridical_address = factory.Faker("address")
    phone_number = factory.Faker("phone_number")
    parent = factory.SubFactory(
        "myapp.tests.factories.BaseOrganizationFactory",
    )


@pytest.mark.django_db
class TestBaseOrganization:
    @pytest.fixture(autouse=True)
    def setup(self):
        self.base_organization = BaseOrganizationFactory(
            parent=None
        )

如果我在设置方法中调用 BaseOrganizationFactory 它会导致 RecursionError: 调用 Python 对象时超出最大递归深度

python python-3.x django pytest factory-boy
1个回答
0
投票

这是因为 BaseOrganizationFactory 创建了一个循环引用,其父字段指向其自身。这会在工厂创建过程中创建无限递归。

更改工厂以避免创建循环引用。 一种方法是将父字段设置为 None 或随机值。 根据您的业务逻辑需要更改逻辑

class BaseOrganizationFactory(factory.django.DjangoModelFactory):
   """Base organization factory"""
   name = factory.Faker("company")
   juridical_address = factory.Faker("address")
   phone_number = factory.Faker("phone_number")

   # Using factory.LazyAttribute to avoid circular reference
   parent = factory.LazyAttribute(lambda o:BaseOrganization.objects.order_by("?").first())

   class Meta:
        model = BaseOrganization
© www.soinside.com 2019 - 2024. All rights reserved.