Django doesn't log the user in

I have a login function, however when I try to login with a user that is not admin Django's authenticate function returns None even though the user exists in the database and the function receives the right username and password.

def login_user(request):

    if request.method == "POST":
        username = request.POST["username"]
        password = request.POST["password"]
        print(username, password)
        user = authenticate(username=username, password=password)
        print(user)
        if user is not None:
            login(request, user)
            return redirect("/")
        else:
            return render(request, "orders/login.html", 
            {"message":"Username and password did not match."})
    else:
        return render(request, "orders/login.html")

login template:

{% extends "orders/layout.html" %}

{% block title %}
    Login
{% endblock %}

{% block body %}

  <div class="forms">
    <form action="{% url 'login' %}" method="post">
      {% csrf_token %}
      <div class="form-group">
        <label>Username</label>
        <input class="form-control" placeholder="Username" name="username">
      </div>
      <div class="form-group">
        <label>Password</label>
        <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" name="password">
        {% if message %}
          <small id="emailHelp" class="form-text text-muted">{{ message }}</small>
        {% endif %}
      </div>
      <button type="submit" class="btn button" id="button1" >Log In</button>
      <a class="btn button" href="{% url 'register' %}" role="button" id="button2">Register</a>
    </form>
  </div>

{% endblock %}

url.py :

from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("menu/<product>/", views.menu, name="menu"),
    path("register", views.register, name="register"),
    path("add_to_cart", views.addToCart, name="add_to_cart"),
    path("cart", views.cart, name="cart"),
    path("confirm", views.confirm, name="confirm"),
    path("login", views.login_user, name="login"),
    path("logout", views.logout_user, name="logout")
]

2 answers

  • answered 2019-07-21 22:04 Farhani Walid

    Try this :

    def login_user(request):
    
        if request.method == "POST":
            username = request.POST["username"]
            password = request.POST["password"]
            print(username, password)
            if username and password:
                user = authenticate(username=username, password=password)
                if user is not None:
                    login(request, user)
                    return redirect("/")
                else:
                    return render(request, "orders/login.html", 
                        {"message":"User does not exist."})
            else:
                return render(request, "orders/login.html", 
                {"message":"Username and password did not match."})
        else:
            return render(request, "orders/login.html")
    

  • answered 2019-07-22 05:58 user11418935

    I think it's better to use django forms rather than just getting the value formrequest.POST. You can try like this:

    forms.py

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

    views.py

    def login_user(request):
        if request.method == "POST":
            form = LoginForm(request.POST or None)
            if form.is_valid():
              username = form.cleaned_data['username']
              password = form.cleaned_data['password']
              print(username, password)
              user = authenticate(request,username=username, password=password)
              print(user)
              if user and user.is_active:
                 login(request, user)
                 return redirect("/")
              else:
                 messages.error(request,'Invalid username and password')
        else:
             form = LoginForm()
        return render(request, "orders/login.html",{'form'"form})
    

    In the template you can render the forms like this:

    template

    <form action="{% url 'login' %}" method="post">
          {% csrf_token %}
          {{form.as_p}}
            {% if message %}
              <small id="emailHelp" class="form-text text-muted">{{ message }}</small>
            {% endif %}
          </div>
          <button type="submit" class="btn button" id="button1" >Log In</button>
          <a class="btn button" href="{% url 'register' %}" role="button" id="button2">Register</a>
        </form>