
本文详解 Factory Boy 中因模块与类同名导致的导入错误,重点说明 TypeError: 'module' object is not callable 和 AttributeError: no attribute 'create' 的根本原因及标准解决方案。
本文详解 factory boy 中因模块与类同名导致的导入错误,重点说明 `typeerror: 'module' object is not callable` 和 `attributeerror: no attribute 'create'` 的根本原因及标准解决方案。
在 Django 项目中使用 Factory Boy 进行测试数据构造时,一个常见却容易被忽视的陷阱是:工厂类与其所在 Python 文件(模块)命名冲突。例如,将工厂类命名为 WebShareFileFactoryBoy,同时又将其定义在名为 WebShareFileFactoryBoy.py 的文件中——这会导致 Python 将该文件识别为一个模块(module),而非可调用的类,从而引发两类典型错误:
- TypeError: 'module' object is not callable:当你执行 WebShareFileFactoryBoy() 时,Python 实际调用的是模块对象,而模块不可调用;
- AttributeError: module '...' has no attribute 'create':WebShareFileFactoryBoy.create() 失败,是因为你试图从模块对象上调用类方法,但模块本身并未暴露该类。
✅ 正确做法是严格分离模块名与类名。推荐采用语义清晰、小写加下划线的模块命名规范,例如将工厂定义文件命名为 factories.py(而非 WebShareFileFactoryBoy.py),并在其中定义类:
# webshare/tests/factories.py
import factory
from webshare.models import WebShareFileFolders
class WebShareFileFactory(factory.django.DjangoModelFactory):
class Meta:
model = WebShareFileFolders
inode = factory.Sequence(lambda n: n)
name = factory.Faker('name')
path = factory.Faker('text', max_nb_chars=50)
is_dir = factory.Faker('boolean')随后,在 Django Shell 或测试中,通过显式导入类来使用:
# ✅ 正确导入方式 from webshare.tests.factories import WebShareFileFactory # 创建实例(保存到数据库) instance = WebShareFileFactory.create() # 或仅构建内存对象(不保存) instance_stub = WebShareFileFactory.build()
⚠️ 注意事项:
- 避免 from xxx import *,它可能掩盖命名冲突;
- 若必须重命名模块(如 webshare/tests/WebShareFileFactoryBoy.py),则必须用 from webshare.tests.WebShareFileFactoryBoy import WebShareFileFactoryBoy 导入类——但这违背 PEP 8,不推荐;
- Factory Boy 3.3+ 要求 DjangoModelFactory 必须通过 .create()(持久化)或 .build()(非持久化)调用,直接调用类(WebShareFileFactory())会报错,因其无默认 __call__ 行为。
总结:问题本质是 Python 导入机制与命名约定的冲突,而非 Factory Boy 配置错误。遵循「模块小写、类名 PascalCase」的命名惯例,并确保导入路径指向类而非同名模块,即可彻底规避此类问题。


















