Django测试UpdateView时模型未更新、返回200状态码问题排查
问题原因及解决方法
核心问题原因
你遇到的两个问题(返回200而非302、数据未更新)本质是同一个原因:表单校验失败。Django的UpdateView在表单校验不通过时,不会执行数据库更新逻辑,也不会触发重定向,会直接返回200状态码重新渲染表单页面。
具体导致校验失败的错误有两个:
- 表单类
PatientUpdateForm存在字段定义错误:你在__init__方法中手动新增了gender和marriage_status两个字段,但Patient模型中不存在这两个字段,且模型里的性别字段名是sex不是gender。多余字段不存在对应模型字段、也没有传入有效值,直接导致校验失败。 - 测试用例提交的POST数据不全:模型中
last_name、hospital_number、age、weight都设置了blank=False为必填项,你测试时只传了first_name和sex两个字段,其余必填字段值为空,自然无法通过校验。
浏览器手动测试正常是因为编辑页渲染时会自动填充所有字段的初始值,提交时哪怕你只修改两个字段,其余字段的现有值也会随请求一起提交,所以能通过校验。
修复步骤
1. 修正PatientUpdateForm定义
删除多余的不存在字段定义,不要新造模型里没有的字段名,如果需要自定义sex字段的选项,直接修改已有sex字段的属性即可:
class PatientUpdateForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 直接修改已有sex字段的选项,不要新增gender字段 self.fields['sex'].choices = [ ('male', 'Male'), ('female', 'Female') ] # 如果需要marriage_status字段,请先在Patient模型中添加对应字段,再取消下面注释 # self.fields['marriage_status'] = forms.ChoiceField(choices=[ # ('married', 'Married'), # ('single', 'Single') # ]) class Meta: model = Patient fields = [ 'first_name', 'last_name', 'hospital_number', 'age', 'sex', 'weight' ]
*额外提醒:你的Patient模型中weight字段错误引用了gender_choices作为选项,属于笔误,请记得修正为体重对应的选项。
2. 补全测试用例的POST数据
测试时提交的data需要包含表单要求的所有必填字段的有效值,和浏览器提交的逻辑保持一致:
def test_patient_update_view(self): data = { 'first_name':'Joe', 'last_name': 'doe', 'hospital_number': 2, 'age':24, 'sex' :'female', 'weight': '79 Kg', } new_patient = Patient.objects.create( first_name='John', last_name = 'doe', hospital_number = 2, age=24, sex = 'male', weight='79 Kg', ) self.client.login(username=self.superuser.username, password='password') response = self.client.post(reverse('patient_edit', kwargs={'pk': new_patient.id}), data) self.assertEqual(response.status_code, 302) new_patient.refresh_from_db() self.assertEqual(new_patient.first_name, 'Joe') self.assertEqual(new_patient.sex, 'female') self.client.logout()
修改完成后重新运行测试即可正常通过。
内容的提问来源于stack exchange,提问作者Mosky1970
相关产品推荐
相关产品推荐

