You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义Inline FormSet的clean校验逻辑单元测试问题

Django自定义Inline FormSet单元测试解决方案

报错原因

你遇到的Select a valid choice. That choice is not one of the available choices.错误是两个传值问题导致的:

  • 关联字段(外键、选择字段)直接传入了Python模型实例,Django表单校验时要求传入的是字符串格式的主键值
  • 布尔字段直接传入了Python布尔类型对象,表单提交数据是字符串类型,需要传入'True'/'False'格式的值

正确的测试写法

1. 手动构造符合要求的提交数据

把所有非字符串类型的字段值做序列化转换:

data = {
    'client_agreements-TOTAL_FORMS': '2',
    'client_agreements-INITIAL_FORMS': '2',
    # 主键字段传字符串格式的主键值
    'client_agreements-1-id': str(self.second_client_agreement.pk),
    # 外键字段同样传字符串格式的关联对象主键
    'client_agreements-1-agreement': str(self.second_client_agreement.agreement.pk),
    # 布尔字段传字符串格式的布尔值
    'client_agreements-1-is_default': 'False',
    'client_agreements-0-id': str(self.online_client_agreement.pk),
    'client_agreements-0-agreement': str(self.first_client_agreement.agreement.pk),
    'client_agreements-0-is_default': 'True',
}

2. 自动生成前缀避免拼写错误

手动拼字段前缀容易出错,可以用formset自带的add_prefix方法自动生成正确的字段名:

# 先定义不带前缀的表单数据
form_datas = [
    {
        "id": self.online_client_agreement.pk,
        "agreement": self.first_client_agreement.agreement.pk,
        "is_default": True
    },
    {
        "id": self.second_client_agreement.pk,
        "agreement": self.second_client_agreement.agreement.pk,
        "is_default": False
    }
]

# 实例化空formset拿到前缀规则
base_formset = formset(instance=self.second_client)
data = {}
# 自动生成管理表单字段
data.update(base_formset.management_form.initial)
# 自动生成带前缀的表单字段
for idx, item in enumerate(form_datas):
    for k, v in item.items():
        data[base_formset.add_prefix(f"{idx}-{k}")] = str(v) if v is not None else ""

3. 校验clean逻辑

不需要执行save操作,调用is_valid()就会触发clean方法,直接校验结果即可:

client_formset = formset(data=data, instance=self.second_client)
# 执行校验(会触发自定义clean逻辑)
is_valid = client_formset.is_valid()

# 调试用:打印错误信息排查问题
# print(client_formset.errors)
# print(client_formset.non_form_errors())

# 断言你的自定义校验逻辑是否生效
# 示例:校验是否触发了“只能有一个默认协议”的错误
assert "只能存在一个默认协议" in client_formset.non_form_errors()

内容的提问来源于stack exchange,提问作者Alexander Skopintsev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 03:39:03