Django’s self.client.login(…) does not work in unit tests

The code that doesn’t work:

from django.contrib.auth.models import User
from django.test import Client

user = User.objects.create(username="testuser", password='12345')

c = Client()
logged_in = c.login(username="testuser", password='12345')

Why doesn’t it work?

In the snippet above, when the `User` is created the actual password hash is set to be `12345`. When the client calls the `login` method, the value of the `password` argument, `12345`, is passed through the hash function, resulting in something like

hash('12345') = 'adkfh5lkad438....'

This is then compared to the hash stored in the database, and the client is denied access because 'adkfh5lkad438....' != '12345'

The Solution

The proper thing to do is call the set_password function, which passes the given string through the hash function and stores the result in User.password.

In addition, after calling set_password we must save the updated User object to the database:

user = User.objects.create(username="testuser")
user.set_password('12345')
user.save()

c = Client()
logged_in = c.login(username="testuser", password='12345')

OR, using more specialized APIs:

# this encodes the password and calls save()
user = User.objects.create_user(username="testuser", password='12345')

c = Client()
logged_in = c.login(username="testuser", password='12345')

If you want a super user, use create_superuser.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)