Django - Login con Email y Contraseña

Por defecto Django solo nos deja identificarnos con el nombre de usuario (username) y la contraseña (password) . A priori práctico. Pero la realidad es peculiar. El ser humano no es una base de datos, por lo que tiende a olvidar. Necesitamos un sistema para que el usuario medio no tenga que memorizar mucho. Sin dejar de lado la contraseña… Habría que realizar un sistema para no solo recuperar la contraseña en caso de perdida, sino para además obtener el nombre de usuario. Y claro, con algún tipo de pregunta de seguridad… que no se olvide la respuesta… que se envíe un Email con un token… ¡Paren las rotativas! ¡KISS! (Keep it Simple, Stupid!). La simplicidad es nuestro objetivo. Cambiemos el nombre de usuario por el email. No es la solución, pero si un principio.

Paso 1

Creamos un nuevo documento Python con el nombre backends.py dentro de la aplicación (a la altura de views.py y models.py). Y pegamos el contenido:

from django.contrib.auth import backends
from django.contrib.auth.models import User

class EmailAuthBackend(backends.ModelBackend):
    """
    Email Authentication Backend

    Allows a user to sign in using an email/password pair, then check
    a username/password pair if email failed
    """

    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            try:
                user = User.objects.get(username=username)
                if user.check_password(password):
                    return user
            except User.DoesNotExist:
                return None

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

Paso 2

En settings.py, modificamos:

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
)

Añadiremos la ruta de nuestra nueva clase.

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'apps.backend.backends.EmailAuthBackend'
)

Pase 3

Ya podemos realizar un sencillo login. Supongamos que estamos en views.py y recibo un formulario con dos campos de POST.

from django.contrib.auth import authenticate, login

def user_login(request):
    '''
    Login
    '''
    if request.method == 'POST':
            user = authenticate(
                username=request.POST['email'],
                password=request.POST['password']
            )
            if user is not None:
                login(request, user)
                return redirect(dashboard)
         

Y se acabó.

En realidad es un híbrido. Comprueba si existe el nombre de usuario y la contraseña, y en caso contrario realiza lo mismo con email y contraseña. Dos en uno.

Espero que este artículo sea de ayuda ya que prácticamente no encontré información al respecto.

Versión escritorio