【Django】SubFactory 使用時に循環参照を避ける

投稿日: 2023/12/31
更新日: 2023/12/31
シェア:

URL copied!


概要

Django のテストを書く際に factory_boy をつかっています。このときにリレーションを表現するために SubFactory で別の Factory を使うために import しようとしたところ循環参照になってしまいエラーとなってしまった。
だんだん複雑になっていくとたまにやっちゃいますよね?

解決策

models でもやるように、import せず、文字列で指定(遅延評価)

サンプル

xy_factory.py

import factory
from .models import X, Y
from .a_factory import AFactory 


class XFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = X

    name = factory.Faker('name')
    a = factory.SubFactory(AFactory)

class YFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Y

    name = factory.Faker('name')

a_factory.py

import factory
from .models import A
from .xy_factory import YFactory 


class AFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = A

    name = factory.Faker('name')
    y = factory.SubFactory(YFactory)
  1. どこかで XFactory 呼びたい
  2. xy_factory.py (AFactory 参照)
  3. a_factory.py (YFactory 参照) 循環参照発生!

みたいなことが起きる場合

after

xy_factory.py

import factory
from .models import X, Y
# from .a_factory import AFactory 


class XFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = X

    name = factory.Faker('name')
    # 遅延評価
    a = factory.SubFactory('a_factory.AFactory')

class YFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Y

    name = factory.Faker('name')

a_factory.py

import factory
from .models import A
# from .xy_factory import YFactory 


class AFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = A

    name = factory.Faker('name')
    # 遅延評価
    y = factory.SubFactory('xy_factory.YFactory')