为了清楚起见,我有几个相关问题并在一个主题下发布。
# 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.errors
或form.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 %}
谢谢
答案 0 :(得分:10)
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.errors
或form.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">×</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的用例没有帮助。
在OP的情况下,您只需替换
form.has_error()
使用
{% if form.errors %}
<p>Your username and password didn't match.
Please try again.</p>
{% endif %}
假设您在表单中提出了一个验证错误(有关验证表单的Django文档为here和here)。 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。
如果要在模板中手动呈现字段,则也可以手动呈现特定于这些字段的错误。在这种情况下,请勿使用{{ 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">×</span>
</button>
{% endfor %}
替换为上面的内容。
有些方法可以根据表单行是否有错误来为其设置CSS类。参见Styling required or erroneous form rows。