为何未保存表单,数据库中用户邮箱字段却自动变更?
问题分析与解决方案
你的核心问题是条件判断逻辑完全颠倒,加上ModelForm的特性导致意外修改数据库:
- 当前代码把「邮箱未更改」的逻辑当成了「邮箱已更改」来处理,触发了不必要的用户状态修改与保存
- ModelForm在验证通过后会自动将表单数据赋值给
self.object(即当前用户实例),如果此时调用save(),哪怕没调用form.save(),也会把修改后的字段写入数据库
修正后的代码
class EditInfoUserView(UpdateView): model = User form_class = EditInfoUserForm template_name = 'users/profile-edit.html' def form_valid(self, form): current_email = self.object.email new_email = form.cleaned_data['email'] if current_email != new_email: # 邮箱已更改,触发验证流程,不直接保存邮箱修改 user = self.object user.is_active = False # 仅保存is_active字段,避免意外写入新邮箱 user.save(update_fields=['is_active']) reset_email_task(user, new_email) logout(self.request) return HttpResponseRedirect(reverse_lazy('email-done')) else: # 邮箱未更改,正常保存表单其他修改 return super().form_valid(form) def get_success_url(self): return reverse_lazy('profile') def get_object(self, queryset=None): return self.request.user def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['title'] = 'Edit profile' return context
关键修改点
- 颠倒条件判断逻辑:现在真正做到「邮箱更改时触发验证,未更改时正常保存」
- 精确控制保存字段:使用
update_fields=['is_active']只修改用户激活状态,避免把表单中的新邮箱意外写入数据库 - 移除冗余代码:删除了无需重写的
form_invalid方法,用默认实现即可
补充说明
ModelForm在is_valid()通过后,会自动把表单数据同步到绑定的实例(self.object)中,此时如果直接调用实例的save(),会把所有修改后的字段保存到数据库——这就是你误以为「未保存表单但邮箱自动变更」的原因。如果需要在用户验证邮箱后再更新邮箱,可以在reset_email_task对应的验证流程中,单独修改并保存用户的邮箱字段。
内容的提问来源于stack exchange,提问作者user23597190
相关产品推荐
相关产品推荐

