如何找到form.has_errors或form.errors并首先启用错误

时间:2011-11-14 16:13:33

标签: django

为了清楚起见,我有几个相关问题并在一个主题下发布。

# Django/django_bookmarks/urls.py    
urlpatterns = patterns('',
    (r'^$', main_page),
    (r'^user/(\w+)/$', user_page),
    (r'^login/$', 'django.contrib.auth.views.login'),
)    

# login.html
<html>
  <head>
    <title>Django Bookmarks - User Login</title>
  </head>

  <body>
    <h1>User Login</h1>
    {% if form.errors %}
    <p>Your username and password didn't match.
      Please try again.</p>
    {% endif %}
    <form method="post" action=".">
      {% csrf_token %}
      <p><label for="id_username">Username:</label>
    {{ form.username }}</p>
      <p><label for="id_password">Password:</label>
    {{ form.password }}</p>
      <input type="hidden" name="next" value="/" />
      <input type="submit" value="login" />
    </form>
  </body>
</html>

根据book login.html 使用form.has_errors代替form.errors。但是,即使输入错误的用户/密码,form.has_errors也不会打印任何警告消息。经过一番调查后,我将其更改为form.errors,这对我有用。

问题1&gt;应该使用哪一个form.errorsform.has_errors

问题2&gt;如果form.has_errors不起作用,为什么django首先不会抱怨。这本书是为Django 1.0编写的,我使用的是Django 1.3。那是什么原因吗?

问题3&gt;如何检查表单有哪些属性?我尝试了以下内容,并没有提供我需要的信息。

python manage.py shell
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import django.contrib.auth.views
>>> dir(django.contrib.auth.views)
['AuthenticationForm', 'HttpResponseRedirect', 'PasswordChangeForm', 'PasswordResetForm', 'QueryDict', 'REDIRECT_FIELD_NAME', 'RequestContext', 'SetPasswordForm', 'User', '_', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'auth_login', 'auth_logout', 'base36_to_int', 'csrf_protect', 'default_token_generator', 'get_current_site', 'login', 'login_required', 'logout', 'logout_then_login', 'never_cache', 'password_change', 'password_change_done', 'password_reset', 'password_reset_complete', 'password_reset_confirm', 'password_reset_done', 'redirect_to_login', 'render_to_response', 'reverse', 'settings', 'urlparse']
>>>
>>> dir(django.contrib.auth.views.login)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

问题4&gt;何时需要以下声明?

{% csrf_token %}

谢谢

4 个答案:

答案 0 :(得分:10)

forms api中未记录

form.has_errors。我快速查看了源代码,我无法在Django 1.3或1.0.X分支的svn checkout中找到它。在你正在使用的书中,这似乎是一个错误。

在模板中检查form.errors没问题。

如果您尝试在视图中访问form.has_errors,则会获得AttributeError。但是,当尝试访问模板中不存在的变量时,Django不会抱怨,因此{{ form.has_errors }}会无声地失败。有关详细信息,请参阅template variables上的文档。

要自省内部表单上的属性,请在表单对象上使用dir,而不是视图。

>>> from django.contrib.auth.views import AuthenticationForm
>>> dir(AuthenticationForm)

但我建议您改为浏览form api文档。

当您使用Django的cross site request forgery protection时,需要使用csrf令牌。

答案 1 :(得分:2)

form.has_errors只是一个布尔值(True/False)。这是一种方便的方法,用于测试表单是否有错误(显然)。

另一方面,

form.errors是实际的错误数组。

答案 2 :(得分:1)

问题1>应该使用form.errorsform.has_errors哪一个?

form.has_errors例如在视图中工作,而不在模板(django docs)中工作。

在模板中,您应该使用{% if form.errors %} your code goes here {%endif %}

检查错误

问题2>如果form.has_errors不起作用,为什么django首先不抱怨。这本书是为Django 1.0写的,而我正在使用Django 1.3。是这个原因吗?

所有DoesNotExist异常均以静默方式失败。请参见django docs-> ,请注意,django.core.exceptions.ObjectDoesNotExist是所有Django数据库API DoesNotExist异常的基类,具有silent_variable_failure = True因此,如果您将Django模板与Django模型对象一起使用,则任何DoesNotExist异常都将静默失败。

问题4>需要以下陈述时? {% csrf_token %}

如果我没记错的话,当您要发布表单(csrf docs)时总是需要csrf_token

我通常会这样显示错误:

{% if form.errors %}
<div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
    <div id="form_errors">
    {% for key, value in form.errors.items %}
        <span class="fieldWrapper">
            {{ key }}:{{ value }}
        </span>
    {% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}

答案 3 :(得分:0)

我知道这是一个旧线程,但是我偶然发现它试图找到类似的答案,所以我想分享一下我发现的内容。似乎问题2-4已得到充分回答;我只会在问题1中添加一些信息。

我正在使用Django 3.0。

Django Forms API中,我没有找到var detailData:Details! { didSet { DispatchQueue.main.async { self.infected.text = String(self.detailData.cases) self.active.text = String(self.detailData.active) self.recovered.text = String(self.detailData.recovered) } } } ,但是有 一个form.has_errors(请注意,错误是单数的)。我认为这对OP的用例没有帮助。

1。简单修复

在OP的情况下,您只需替换

form.has_error()

使用

{% if form.errors %}
<p>Your username and password didn't match.
  Please try again.</p>
{% endif %}

假设您在表单中提出了一个验证错误(有关验证表单的Django文档为herehere)。 OP使用的是Django的Authentication框架,这会引发OP在表单提交时寻找的验证错误,而无需进行任何其他调整。

使用{{ form.errors }} 还可以确保将来,如果您选择添加更多错误,则无需将这些错误硬编码到模板中。

为方便起见,如果您没有任何错误,{{ form.errors }}不会在呈现页面时向页面添加任何额外的html。默认情况下,Django对于大多数模板变量都无提示地失败。

这不会特别漂亮; @ P.Maino和@Toby Speight的渲染代码将使您在视觉上更具吸引力,但这需要Bootstrap。 Bootstrap声称是“世界上最受欢迎的前端开源工具包”;您可以download or connect via CDN to version 4.5 here

2。稍微复杂些

如果要在模板中手动呈现字段,则也可以手动呈现特定于这些字段的错误。在这种情况下,请勿使用{{ form.errors }};通过在适当的地方使用{{ form.errors }}来呈现非格式错误,以分隔错误消息(我通常会选择格式的顶部,或者在页面顶部有导航条时选择它的正下方)。然后,对于每个单独的字段,使用{{ form.non_form_errors }}渲染每个字段的错误。 Documentation is here; OP的模板如下所示:

{{ form.<field_name>.errors }}

再次,可能不是特别漂亮,但对于用户而言,可能比<!-- login.html --> <html> <head> <title>Django Bookmarks - User Login</title> </head> <body> <h1>User Login</h1> {{ form.non_form_errors }} <!-- Show errors not tied to a field --> <form method="post" action="."> {% csrf_token %} {{ form.username.errors }} <!-- Show errors for the username field --> <p> <label for="id_username">Username:</label> {{ form.username }} </p> {{ form.password.errors }} <!-- Show errors for the password field --> <p> <label for="id_password">Password:</label> {{ form.password }} </p> <input type="hidden" name="next" value="/" /> <input type="submit" value="login" /> </form> </body> </html> 更明显。此方法还可以确保您无需将错误消息硬编码到模板中;但是,您需要将{{ form.errors }}标记添加到每个您希望能够显示错误的新输入。

您可以像这样将{{ form.<field_name>.errors }}打扮成@ P.Maino和@Toby Speight的答案:

{{ form.<field_name>.errors }}

只需将{% for error in form.<field_name>.errors %} <!-- Insert your field name here --> <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert"> {{ error }} </div> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> {% endfor %} 替换为上面的内容。

PS

有些方法可以根据表单行是否有错误来为其设置CSS类。参见Styling required or erroneous form rows