django验证错误消息显示两次

时间:2016-09-22 17:01:04

标签: python django

我只是想在用户因无效的用户名或密码而无法登录时收到错误消息。有没有什么比重写清洁方法更好的原因。我发现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的调用仅显示错误消息一次。

3 个答案:

答案 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