
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.
Django 4.x en adelante
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.backends import BaseBackend
from django.contrib.auth.models import User
class EmailAuthBackend(BaseBackend):
"""
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, request, 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
incluyendo la ruta de nuestro archivo backends.py
. En mi caso app.website.backends
quedando de la siguiente forma.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'app.website.backends.EmailAuthBackend'
)
Paso 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.
Django 3.x
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
incluyendo la ruta de nuestro archivo backends.py
. En mi caso app.website.backends
quedando de la siguiente forma.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'app.website.backends.EmailAuthBackend'
)
Paso 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.
{{ comments.length }} comentarios