django validation error message get displayed twice
<p>I just want to have an error message when user failed to login due to invalid username or password. Is there any preferable why to have it than overriding clean method. I found that django have login_failed signals but i am unsure it best to use that.</p>

<p>Here is the print screen
<a href="http://i.stack.imgur.com/CiGzH.png" rel="nofollow">validation error message get displayed twice</a></p>

<p>Here is my updated code from github :</p>

<p><a href="https://github.com/afdallismen/Django-error-message-displayed-twice" rel="nofollow">https://github.com/afdallismen/Django-error-message-displayed-twice</a></p>

<p>Here is my python version and output from pip list, and pip freeze</p>

<p>python -V</p>

<pre><code>Python 3.5.2
</code></pre>

<p>pip list</p>

<pre><code>Django (1.10.1)
pip (8.1.2)
setuptools (27.1.2)
wheel (0.29.0)
</code></pre>

<p>pip freeze</p>

<pre><code>Django==1.10.1
</code></pre>

<p>forms.py</p>

<pre><code>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))
</code></pre>

<p>view.py</p>

<pre><code>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})
</code></pre>

<p>urls.py</p>

<pre><code>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'),
]
</code></pre>

<p>author_login.html</p>

<pre><code>{% extends "base.html" %}

{% block content %}
{% if form.non_field_errors %}
  &lt;ul&gt;
    {% for error in form.non_field_errors %}
     &lt;li&gt;{{ error }}&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endif %}
&lt;form action="" method="post"&gt;
  {% csrf_token %}
  {{ form.as_p }}
  &lt;input type="submit" value="Login" /&gt;
&lt;/form&gt;
{% endblock %}
</code></pre>

<p>base.html</p>

<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;title&gt;Microblog&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  {% if user.is_authenticated %}
    &lt;p&gt;Welcome, {{ request.user.username }}&lt;/p&gt;
    &lt;a href="{% url 'microblog:author_logout' %}"&gt;Logout&lt;/a&gt;
  {% else %}
    &lt;a href="{% url 'microblog:author_login' %}"&gt;Login&lt;/a&gt;
  {% endif %}
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href="{% url 'microblog:index' %}"&gt;Microblog&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  {% block content %}{% endblock %}
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>As a workaround i tried to sent validation error through form.add_error method in views.py, and removing clean, login and form_invalid method on forms.py. </p>

<p>Here is my new views.py :</p>

<pre><code>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})
</code></pre>

<p>Turn out it still displayed error message twice. Now it seems form.add_error was called twice, was it ?.</p>

<p>Tried this :</p>

<pre><code>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)
</code></pre>

<p>It print 1 and only printed once, so author_login with POST method just executed once, same for else block that print count. But form.add_error get executed twice ?</p>

<p>It just getting weird. Right now i am using from.add_error in views.py. And then in templates i can fetch the error message through messages context and it did shows the message once :</p>

<pre><code>{% if messages %}
    &lt;ul class="messages"&gt;
    {% for message in messages %}
        &lt;li&gt;{{ message }}&lt;/li&gt;
    {% endfor %}
    &lt;/ul&gt;
{% endif %}
</code></pre>

<p>The <code>clean</code> method needs to use <code>super()</code>:</p>

<pre><code>def clean(self):
    cleaned_data = super(AuthorLogin, self).clean() #insert this line
    username = cleaned_data.get('username')
    ...
</code></pre>

python django