Django UpdateView 表单验证错误未在模板中显示

2 投票
2 回答
5073 浏览
提问于 2025-04-18 17:52

我在views.py里有一个更新视图

class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
    model = UserProfile
    template_name = 'my-account/my_profile_update.html'
    form_class = UserProfileUpdateForm

    def get_context_data(self, **kwargs):

        context = super(UserProfileUpdateView, self).get_context_data(**kwargs)
        context['form'] = UserProfileUpdateForm(instance=UserProfile.objects.get(user=self.request.user))
        return context

    def get_object(self):
        return get_object_or_404(UserProfile, user=self.request.user)

forms.py

class UserProfileUpdateForm(forms.ModelForm):

    username = forms.CharField(label='Username')
    video = forms.URLField(required=False, label='Profile Video')

    def clean_username(self):
        username = self.cleaned_data['username']
        if UserProfile.objects.filter(username=username).exists():
            print "This print is working"
            raise forms.ValidationError('Username already exists.')
        return username 

    class Meta:     
        model = UserProfile

但是在模板中,表单的错误信息没有显示出来

在模板home.html中

{{ form.username.errors }}

当输入已存在的用户时,系统会进行验证并抛出错误,但在form.username.errors中没有显示出来。我试着打印表单,但没有发现任何错误。这是更新视图的问题吗?

提前谢谢你们..

2 个回答

1

在你的情况下,UserProfileUpdateForm 已经和 UserProfile 绑定好了,所以你不需要更改 context 数据。

不过,我在尝试给表单设置一些初始值时,遇到了完全相同的问题,那个时候我是按照文档来做的。在 get_context_data 方法里,我写了

context['form'] = self.form_class(instance=self.post, initial={"tags":",".join([tag.name for tag in self.post.tags.all()])})

这样可以让 form.tags 预先填充一个用逗号分隔的与帖子相关的标签列表。

我通过查看 UpdateView 的源代码解决了这个问题。在第81行,他们有

def form_invalid(self, form):
    """
    If the form is invalid, re-render the context data with the
    data-filled form and errors.
    """
    return self.render_to_response(self.get_context_data(form=form))

如果表单无效并且包含错误,它会用绑定的表单调用 get_context_data。我需要把这个表单传递给模板,而不是我在 get_context_data 方法中指定的那个表单。

为了做到这一点,我们需要对 get_context_data 做一些修改。

def get_context_data(self, **kwargs):
    context = super(PostUpdate, self).get_context_data(**kwargs)
    if 'form' in kwargs and kwargs['form'].errors:
        return context
    else:
        context['form'] = self.form_class(instance=self.post, initial={"tags":",".join([tag.name for tag in self.post.tags.all()])})
        return context

如果有一个包含错误的表单,它会直接把这个表单传递给模板。否则,就使用我们提供的那个。

我相信还有其他解决方案。如果你有,请分享出来,这样可以帮助其他人学习 Django。

3

更新视图已经把表单包含在上下文中了。不过,在你的 get_context_data 方法里,你却用下面的代码替换了这个表单:

    context['form'] = UserProfileUpdateForm(instance=UserProfile.objects.get(user=self.request.user))

这个表单没有绑定到提交的数据上,所以它永远不会有任何错误。

你其实不需要加这一行。你的 get_object 方法应该已经足够确保你的视图使用了正确的用户。

撰写回答