如何在Django的views.py中引发ValidationError?

24 投票
3 回答
57142 浏览
提问于 2025-04-16 08:44

我在使用Django的表单功能。我在模型层进行验证:

def clean_title(self):
    title = self.cleaned_data['title']
    if len(title)  < 5:
        raise forms.ValidationError("Headline must be more than 5 characters.")
    return title

不过,有些事情我需要在views.py里验证。例如……用户上次发布内容是不是已经超过一分钟了?

这种情况需要用到request.user,而模型层是无法获取这个信息的。所以,我必须在views.py里进行验证。我该怎么做才能在views.py里实现和这个一样的功能呢?

raise forms.ValidationError("Headline must be more than 5 characters.")

3 个回答

6

你可以在视图中使用消息:

from django.contrib import messages

messages.error(request, "Error!")

文档链接:https://docs.djangoproject.com/es/1.9/ref/contrib/messages/

9

在视图中你不应该使用 ValidationError,因为这个错误主要是用在表单里的。相反,你应该把用户重定向到另一个网址,告诉他们不能这么快再提交。这样处理问题才是正确的。ValidationError 应该在 Form 实例中被触发,当输入的数据不符合要求时才用到。这种情况并不适用。

27

我觉得gruszczy的回答很好,但如果你想进行一些通用的验证,而这些变量你认为只在视图中可用,那我有个替代方案:把这些变量作为参数传递给表单,然后在表单的主要clean()方法中处理它们。

这样做的好处是,你的视图会更简单,所有与表单内容是否合格相关的事情都在表单内部处理。

比如:

# IN YOUR VIEW 
# pass request.user as a keyword argument to the form
myform = MyForm(user=request.user)


# IN YOUR forms.py
# at the top:

from myapp.foo.bar import ok_to_post # some abstracted utility you write to rate-limit posting 

# and in your particular Form definition

class MyForm(forms.Form)

   ... your fields here ...

   def __init__(self, *args, **kwargs):
      self.user = kwargs.pop('user')  # cache the user object you pass in
      super(MyForm, self).__init__(*args, **kwargs)  # and carry on to init the form


   def clean(self):
      # test the rate limit by passing in the cached user object

      if not ok_to_post(self.user):  # use your throttling utility here
          raise forms.ValidationError("You cannot post more than once every x minutes")

      return self.cleaned_data  # never forget this! ;o)

需要注意的是,在clean()方法中抛出一个通用的ValidationError会把错误信息放到myform.non_field_errors里,所以如果你手动显示表单,确保你的模板中包含{{form.non_field_errors}}

撰写回答