如何在 Django 的 views.py 中引发 ValidationError(或做类似的事情)?

Posted

技术标签:

【中文标题】如何在 Django 的 views.py 中引发 ValidationError(或做类似的事情)?【英文标题】:How do I raise a ValidationError (or do something similar) in views.py of my Django? 【发布时间】:2011-05-27 19:30:07 【问题描述】:

我正在使用 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.")

【问题讨论】:

这看起来不像在模型层中进行验证(如在 django.db.models.Model 中。你的意思是 django.forms.Form/ModelForm 层吗?我想是的 我有一个类似的要求,但出于不同的原因:有一个字段有时只需要,具体取决于页面,因此视图需要强制执行它,因为它与页面紧密耦合。 【参考方案1】:

我认为 gruszczy 的答案是一个很好的答案,但是如果您在进行涉及您认为仅在视图中可用的变量的通用验证之后,这里有一个替代方法:将 vars 作为参数传递给表单并在表单的主要 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

【讨论】:

很好的解决方案。这是黑客吗?不过我喜欢它,ty 不,我不会称之为黑客。它只是利用 Django Form 类而不是默认/教程方法。我已经在很多地方使用它并且(只要你知道 pop() 会做什么,因为它会从 kwargs 中删除关键字参数,没有什么可以抓住你的。如果你不想删除它来自 kwargs,请改用 get()。 不错!通过您的解决方案,我可以在表单上传递请求对象,以便检查上传文件的文本内容。【参考方案2】:

您不要在视图中使用ValidationError,因为这些例外与表单一样。相反,您应该将用户重定向到其他网址,这将向他解释,他不能很快再次发布。这是处理这些东西的正确方法。 ValidationError 应在 Form 实例内引发,当输入数据未验证时。事实并非如此。

【讨论】:

我认为这是一个很好的方法,但从可用性的角度来看,将该消息添加为 flash/django.contrib.messages 消息会更好,而 not 重定向到一个新页面,但只是再次呈现已填写的表单。这样,用户可以等待,比如说,50 秒,然后再次提交数据,而无需重新输入所有数据【参考方案3】:

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

from django.contrib import messages

messages.error(request, "Error!")

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

【讨论】:

Messages 是一个简单的表单错误的简单有效的解决方案。 但是在forms.py中如何应用消息?

以上是关于如何在 Django 的 views.py 中引发 ValidationError(或做类似的事情)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中重复调用 views.py 中的函数?

Django - 如何在views.py中访问实例的值

如何在 django views.py 中随机播放列表?

Django绑定表单无效,但未引发ValidationError

Django:如何通过views.py更改值

如何在views.py Django中返回ajax响应以及重定向