2

I am trying to make a Django login screen that shows the errors when the user for example doesn't type the right password. But the only error i am receiving is the "This user doesn't exist!" how can i make the other error messages to show up? What is the problem with my code?

forms.py

class UserLogInForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)

    def clean(self, *args, **kwargs):
        username = self.cleaned_data.get("username")
        password = self.cleaned_data.get("password")
        #if username and password:
        # user = get_user_model()
        user = authenticate(username=username, password= password)
        # user = authenticate(username=username)
        if not user:
            raise forms.ValidationError("This user does not exist!")
        if not user.check_password(password):
            raise forms.ValidationError("Incorrect password!")
        if not user.is_active:
            raise forms.ValidationError("This user is no longer active.")

        return super(UserLogInForm, self).clean(*args, **kwargs)

views.py

def login_view(request):
    title = "Login"
    form = UserLogInForm(request.POST or None)
    if form.is_valid():
        username = form.cleaned_data.get("username")
        password = form.cleaned_data.get("password")
        user = authenticate(username=username, password=password)
        login(request, user)
        return redirect('/')

    return render(request, "form.html", {"form": form, "title": title, 'errors': form.non_field_errors()})

form.html

 <form method='POST' action='' enctype="multipart/form-data">{% csrf_token %}
        {{ form.non_field_errors }}
        <table align="center">
            <tr>
                <td>{{ form.username.label_tag }}</td>
                <td>{{ form.username }}</td>
            </tr>
            <tr>
                <td>{{ form.password.label_tag }}</td>
                <td>{{ form.password }}</td>
            </tr>
      </table>
        <div id="wrapper">
        <button id="button" type="submit">Login</button>
        </div>
    </form>
2
  • you dont have any problem with your code, but if a user doesnt exist how will the form go to the next validation? it will render the error that it first encounters Commented Jun 25, 2017 at 16:01
  • The other exceptions will never be raised because a) the first exception ends the execution and b) if the user is not authenticated, user will become None. If you want to raise more specific errors, raise them in authenticate(). Commented Jun 25, 2017 at 16:02

2 Answers 2

2

The authenticate function from django.contrib.auth is written so,

The function takes credentials as keyword arguments, username and password for the default case, checks them against each authentication backend, and returns a User object if the credentials are valid for a backend. If the credentials aren’t valid for any backend or if a backend raises PermissionDenied, it returns None.

So, if you want raise password check errors, it should be before calling authenticate function. You may need to check the user model itself. Either you could validate in the forms or views.

You could check whether the user is valid before logging in,

from django.contrib.auth.models import User

class UserLogInForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)

    def clean(self, *args, **kwargs):
        username = self.cleaned_data.get("username")
        password = self.cleaned_data.get("password")
        #if username and password:
        # user = get_user_model()
        try:            
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            raise forms.ValidationError("This user does not exist!")  
        if user and not user.check_password(password):
            raise forms.ValidationError("Incorrect password!"):
        if user and not user.is_active:
            raise forms.ValidationError("This user is no longer active.")
        return super(UserLogInForm, self).clean(*args, **kwargs)

And in your views.py,

user = authenticate(username=username, password=password)
if user is not None:
    login(request, user)
    return redirect('/')
return render(request, "form.html", {"form": form, "title": title, 'errors': form.non_field_errors()})
Sign up to request clarification or add additional context in comments.

2 Comments

Very good answer, but I'd like to add a warning: If you tell your user what is wrong, you're also telling someone that tries to hack into their account what is wrong. This is why login form feedback is intentionally vague.
That being said (which is true in most of the cases), I would like to point out that the question of OP was regarding the speculation of the error raised. Then, there requires a trade off between both the circumstances, which would be the fact that usage of such error message should only be restricted to development environments. Also, appreciate your remark about the security inconsistency.
0

You can modify your form.html :) here is the sample code:

note: I presume you already know how to use bootstrap.

 {% if user is not None %}
 <div class="alert alert-danger alert-dismissable">
       <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
        <p>The username does not exist!</p>
 </div>
{% endif %}

Don't forget the {% endif %} function.

Well, this just a basic functionality in Django.

Besides, you can simplify your Login in views.py

def User_Logins(request):
if request.method == 'POST':
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')

    user = authenticate(username=username, password=password)
    if user is not None and user.is_active:
        login(request, user)
        return redirect('/')
    return redirect('/')
return render(request, './', {'Login_form': UserLoginForm})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.