Django表单验证失败后{{user.username}}显示错误值的问题
Django用户资料更新表单验证失败后用户名显示异常问题
问题现象
提交未通过验证的表单(例如输入已存在的用户名)时,数据库并未发生变更,但页面中的{{user.username}}却显示为这个未通过验证的错误用户名,期望保持与数据库中登录用户的原有数据一致。
原因分析
当你创建UserUpdateForm时传入了request.POST和instance=request.user,Django的ModelForm会将POST提交的内容直接更新到传入的instance对象的内存属性中——哪怕你没调用save()将修改写入数据库,request.user这个对象在内存里的属性已经被改掉了。模板渲染时读取的是这个内存中的修改后的值,而非数据库里的原始数据。
解决方案
方法一:使用数据库获取的独立用户实例
修改views.py中的POST处理逻辑,从数据库重新获取一个独立的用户实例作为表单的instance,这样修改的是副本,不会影响request.user的原始值:
@login_required def profile(request): if request.method == 'POST': # 从数据库重新获取用户实例,避免修改request.user的内存属性 user_instance = User.objects.get(pk=request.user.pk) u_form = UserUpdateForm(request.POST, instance=user_instance) p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() messages.success(request, f'Account has been updated') return redirect('profile') else: u_form = UserUpdateForm(instance=request.user) p_form = ProfileUpdateForm(instance=request.user.profile) context = { 'u_form': u_form, 'p_form': p_form } return render(request, 'users/profile.html', context)
方法二:验证失败后刷新用户实例
如果不想改动表单初始化逻辑,可以在验证失败后,强制刷新request.user从数据库重新读取原始数据:
@login_required def profile(request): if request.method == 'POST': u_form = UserUpdateForm(request.POST, instance=request.user) p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() messages.success(request, f'Account has been updated') return redirect('profile') # 验证失败时,刷新request.user从数据库获取原始数据 request.user.refresh_from_db() else: u_form = UserUpdateForm(instance=request.user) p_form = ProfileUpdateForm(instance=request.user.profile) context = { 'u_form': u_form, 'p_form': p_form } return render(request, 'users/profile.html', context)
两种方法都能解决问题,第一种更稳妥,避免意外修改request.user;第二种代码改动更小。
内容的提问来源于stack exchange,提问作者hodini
相关产品推荐
相关产品推荐

