我只是想在用户因无效的用户名或密码而无法登录时收到错误消息。有没有什么比重写清洁方法更好的原因。我发现django有login_failed信号,但我不确定最好使用它。
这是打印屏幕 validation error message get displayed twice
这是我在github上的更新代码:
https://github.com/afdallismen/Django-error-message-displayed-twice
这是我的python版本和pip list的输出,以及pip freeze
python -V
Python 3.5.2
点子列表
Django (1.10.1)
pip (8.1.2)
setuptools (27.1.2)
wheel (0.29.0)
冻结
Django==1.10.1
forms.py
class AuthorLogin(forms.Form):
username = forms.CharField(label='Your name', max_length=100)
password = forms.CharField(
label='Your password',
max_length=100,
widget=forms.PasswordInput)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if not user or not user.is_active:
raise forms.ValidationError('Invalid username or password', code='invalid')
return self.cleaned_data
def login(self, request):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
return user
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
view.py
def author_login(request):
form = AuthorLogin(request.POST or None)
if request.POST and form.is_valid():
user = form.login(request)
if user is not None:
login(request, user)
return redirect('microblog:index')
return render(request, 'microblog/author_login.html', {'form': form})
urls.py
app_name = 'microblog'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^login/', views.author_login, name='author_login'),
url(r'^logout/', views.author_logout, name='author_logout'),
]
author_login.html
{% extends "base.html" %}
{% block content %}
{% if form.non_field_errors %}
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Login" />
</form>
{% endblock %}
base.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microblog</title>
</head>
<body>
{% if user.is_authenticated %}
<p>Welcome, {{ request.user.username }}</p>
<a href="{% url 'microblog:author_logout' %}">Logout</a>
{% else %}
<a href="{% url 'microblog:author_login' %}">Login</a>
{% endif %}
<nav>
<ul>
<li><a href="{% url 'microblog:index' %}">Microblog</a></li>
</ul>
</nav>
{% block content %}{% endblock %}
</body>
</html>
作为一种解决方法,我尝试通过views.py中的form.add_error方法发送验证错误,并删除forms.py上的clean,login和form_invalid方法。
这是我的新views.py:
def author_login(request):
if request.method == 'POST':
form = AuthorLogin(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('microblog:index')
else:
form.add_error(None, 'Invalid username or password.') # This line seems to get executed twice
else:
form = AuthorLogin()
return render(request, 'microblog/author_login.html', {'form': form})
结果显示仍然显示错误信息两次。现在看来form.add_error被调用了两次,是吗?。
试过这个:
def author_login(request):
if request.method = 'POST':
count = 0
...
if form.is_valid()
....
if user is not None:
....
else:
count = count + 1
print(count)
它打印1并且只打印一次,因此使用POST方法的author_login只执行一次,对于打印计数的else块也是如此。但是form.add_error会被执行两次吗?
修复
似乎form.non_field_errors包含在form.errors中。删除模板中对forms.non_field_errors的调用仅显示错误消息一次。
答案 0 :(得分:1)
循环浏览form.non_field_errors
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
以及使用form.as_p
时的一次
{{ form.as_p }}
如果您使用form.as_p
,那么您不必手动呈现form.non_field_errors
。如果您确实手动显示form.non_field_errors
,那么您必须单独呈现表单字段,而不是使用form.as_p
。
有关详细信息,请参阅working with forms in templates上的文档。
答案 1 :(得分:0)
clean
方法需要使用super()
:
def clean(self):
cleaned_data = super(AuthorLogin, self).clean() #insert this line
username = cleaned_data.get('username')
...
答案 2 :(得分:0)
您可以按照文档中的描述尝试此操作:
def clean(self):
super(AuthorLogin, self).clean()
...
# not return anything