Django表单无错误却验证不通过?单元测试调试遇异常
这种情况我之前踩过好几次坑,大概率是表单验证的隐性逻辑或者测试代码的细节没处理对,给你几个具体的排查方向:
先确认表单是否处于绑定状态
这是最容易忽略的点!如果你只是用instance初始化表单(就像你代码里的form = PackageForm(instance=package)),此时表单是未绑定状态,调用is_valid()会直接返回False,而且errors是空的——因为根本没有提交的数据可供验证。
如果你要测试表单的更新验证逻辑,需要同时传入data和instance,比如:# 把package的字段转换成表单接受的字典格式 form_data = { 'name': package.name, 'description': package.description, # 其他表单需要的字段... } form = PackageForm(data=form_data, instance=package) print(form.is_valid()) # 现在再看结果在调试器里你也可以先输
form.is_bound,如果返回False,那就是这个问题。检查自定义验证逻辑的错误抛出
如果表单有自定义的clean()方法或者跨字段验证器,有时候错误没有被正确关联到字段,而是存在non_field_errors里。你可以在调试器里执行form.non_field_errors(),说不定能找到隐藏的错误信息。
比如如果你的表单验证要求package的某个字段和关联的company属性匹配,但factory生成的数据刚好不满足,这种错误可能不会显示在单个字段的errors里。核对factory生成的数据是否符合表单规则
虽然factory_boy生成的实例看起来正常,但可能某些字段不符合表单的隐性要求:- 比如表单字段设置了
max_length=50,但factory默认生成的字符串长度超过了这个值; - 或者表单要求字段是唯一值,但factory生成的重复了;
- 再或者关联的
company实例有状态限制(比如必须是激活状态),但factory生成的company是未激活的。
你可以在调试器里打印package.__dict__,把每个字段的值和表单的定义逐一比对,就能发现问题。
- 比如表单字段设置了
查看更详细的错误信息
在调试器里别只看form.errors,试试form.errors.as_data(),它会返回所有错误的结构化信息,包括那些没有显示在前端的隐性错误,能帮你更快定位问题。
内容的提问来源于stack exchange,提问作者Kurt Peek

