Pytest配合mixer测试Django模型时传入非模型字段未报错问题
1. mixer允许传入非模型字段的原因
这是mixer的内置设计特性:调用mixer.blend()生成模型实例时,会将入参分为两类处理:
- 和模型字段匹配的参数:会传入Django模型构造方法,最终写入数据库
- 和模型字段不匹配的参数:不会进入模型初始化逻辑,而是直接作为自定义属性挂载到生成的实例对象上,方便测试时临时附加自定义属性,不需要修改模型定义。
2. 测试运行不报错的原因
有两个底层规则支撑这个表现:
- Python本身是动态语言,默认允许给任意类的实例动态绑定额外属性,不会抛出语法错误,除非类显式定义了
__slots__限制允许的属性范围。 - 你代码中的
non_model_field已经被mixer绑定到了生成的project实例上,所以断言访问该属性时不会触发AttributeError,测试自然不会报错。
注意:这个额外属性仅存在于当前内存中的实例对象上,不会写入数据库。如果你重新从数据库查询该实例,访问
non_model_field会直接报错,你可以用下面的代码验证:project_from_db = Project.objects.get(pk=project.pk) # 下面的断言会失败 assert hasattr(project_from_db, 'non_model_field')
你遗漏的相关规则
- Django ORM默认不会在实例初始化阶段校验入参,只有调用
full_clean()方法时才会校验模型字段的合法性,且不会校验动态绑定的额外属性。 - mixer的额外参数仅作用于当前内存实例,不会持久化到数据库。
- Python动态属性绑定的语法特性,没有静态语言的严格属性校验。
内容的提问来源于stack exchange,提问作者Msw Tm
相关产品推荐
相关产品推荐

