FormSet 是「一次提交多个同类表单」的机制。它靠什么知道有几个表单?怎么限制数量?inline 是怎么关联父对象的?为什么渲染时会发 N 次查询?这篇逐项验证。
未绑定 FormSet 的 management_form 初始值: {'TOTAL_FORMS': 2, 'INITIAL_FORMS': 0, 'MIN_NUM_FORMS': 0, 'MAX_NUM_FORMS': 1000}
渲染出的隐藏字段: ['<input type="hidden" name="form-TOTAL_FORMS" value="2" id="i', '<input type="hidden" name="form-INITIAL_FORMS" value="0" id=']
有 ManagementForm:is_valid() = True cleaned = [{'x': 1}, {'x': 2}]
缺 ManagementForm:is_valid() = False non_form_errors = ['ManagementForm data is missing or has been tampered with. Missing fields: form-TOTAL_FORMS, form-INITIAL_FORMS. You may need to file a bug report if the issue persists.'] code = missing_management_form模板里忘了渲染 {{ formset.management_form }},提交时就是这个错误——看起来像「表单坏了」,其实是缺隐藏字段。
未绑定:表单数 = 3 (min_num 2 + extra 1)
只提交 1 个:is_valid() = False ['Please submit at least 2 forms.']
提交 5 个(max_num=3):is_valid() = False ['Please submit at most 3 forms.']
第 2 个勾选 DELETE:cleaned_data = [{'x': 1, 'DELETE': False}, {'x': 2, 'DELETE': True}, {'x': 3, 'DELETE': False}] deleted_forms = 1min_num/max_num 默认只影响「显示几个」;要拒绝不符合数量的提交,必须 validate_min/validate_max。实测未绑定 FormSet 的 MAX_NUM_FORMS 初始值是 1000(没有测提交超过它时的行为)。
is_valid = True 表单字段: ['title', 'id', 'DELETE', 'author']
save() 发出的查询数: 2 保存的对象: [('b1', True), ('b2', True)]
再打开编辑页:表单数 = 4 (2 个已有 + extra 2) INITIAL_FORMS = 2父对象通过 instance= 传入,外键字段由 Django 自动处理。
10 本书、每本一个 editor 下拉框,渲染整个 FormSet 的查询数: 11
查询种类: {'SELECT "lab_book"."id", "lab_book"."author_id", "lab_book"."title", "l': 1, 'SELECT "lab_editor"."id", "lab_editor"."name" FROM "lab_editor"': 10}每个表单实例创建自己的 ModelChoiceField 选项,渲染时各自查询。表单数多、选项字段多时明显。