pelicula - django wikipedia
Django-Iniciar sesión con correo electrónico (9)
Quiero que django autentique a los usuarios por correo electrónico, no a través de nombres de usuario.
Una forma puede ser proporcionar valor de correo electrónico como valor de nombre de usuario, pero no quiero eso.
La razón es que tengo una url
/profile/<username>/
, por lo tanto, no puedo tener una url
/profile/[email protected]/
.
Otra razón es que todos los correos electrónicos son únicos, pero a veces sucede que el nombre de usuario ya está siendo utilizado.
Por lo tanto, estoy creando automáticamente el nombre de usuario como
fullName_ID
.
¿Cómo puedo cambiar dejar que Django se autentique con el correo electrónico?
Así es como creo un usuario.
username = `abcd28`
user_email = `[email protected]`
user = User.objects.create_user(username, user_email, user_pass)
Así es como inicio sesión.
email = request.POST[''email'']
password = request.POST[''password'']
username = User.objects.get(email=email.lower()).username
user = authenticate(username=username, password=password)
login(request, user)
¿Hay algún otro inicio de sesión aparte de obtener primero el nombre de usuario?
Django 2.x
Como mencionó Ganesh anteriormente para django 2.x, el método de autenticación ahora requiere un parámetro de solicitud.
# backends.py
from django.contrib.auth import backends, get_user_model
from django.db.models import Q
UserModel = get_user_model()
class ModelBackend(backends.ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
# user = UserModel._default_manager.get_by_natural_key(username)
# You can customise what the given username is checked against, here I compare to both username and email fields of the User model
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
return super().authenticate(request, username, password, **kwargs)
agregue su back-end a la configuración de su proyecto
# settings.py
AUTHENTICATION_BACKENDS = [''path.to.ModelBackend'']
Su modelo de usuario personalizado tendrá que hacer que los correos electrónicos sean únicos para usuarios activos y validados. Puede hacer esto simplemente con algo como esto:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
objects = UserManager()
email = models.EmailField(_(''email address''), unique=True)
class Meta:
verbose_name = _(''user'')
verbose_name_plural = _(''users'')
db_table = ''auth_user''
swappable = ''AUTH_USER_MODEL''
Pero para evitar que alguien bloquee el uso de su correo electrónico, debe agregar una validación de correo electrónico y hacer que su proceso de registro e inicio de sesión tenga en cuenta que los correos electrónicos pueden no ser únicos (y probablemente evitar que los nuevos usuarios usen una dirección de correo electrónico existente y validada).
Debe personalizar la clase ModelBackend. Mi código simple:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class YourBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
if ''@'' in username:
UserModel.USERNAME_FIELD = ''email''
else:
UserModel.USERNAME_FIELD = ''username''
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
Y en el archivo settings.py , agregue:
AUTHENTICATION_BACKENDS = [''path.to.class.YourBackend'']
Debería escribir un backend de autenticación personalizado. Algo como esto funcionará:
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class EmailBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
Luego, configure ese backend como su backend de autenticación en su configuración:
AUTHENTICATION_BACKENDS = [''path.to.auth.module.EmailBackend'']
Actualizado
ModelBackend
de
ModelBackend
ya que implementa métodos como
get_user()
ya.
Para Django 2
username = get_object_or_404(User, email=data["email"]).username
user = authenticate(
request,
username = username,
password = data["password"]
)
login(request, user)
Si está comenzando un nuevo proyecto, django le recomienda encarecidamente que configure un modelo de usuario personalizado. (ver https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project )
y si lo hizo, agregue tres líneas a su modelo de usuario:
class MyUser(AbstractUser):
USERNAME_FIELD = ''email''
email = models.EmailField(_(''email address''), unique=True) # changes email to unique and blank to false
REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS
Luego,
authenticate(email=email, password=password)
funciona, mientras que
authenticate(username=username, password=password)
deja de funcionar.
Tenía un requisito similar en el que el nombre de usuario / correo electrónico debería funcionar para el campo de nombre de usuario. En caso de que alguien esté buscando la forma de autenticación del backend, consulte el siguiente código de trabajo. Puede cambiar el conjunto de consultas si solo desea el correo electrónico.
from django.contrib.auth import get_user_model # gets the user_model django default or your own custom
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
# Class to permit the athentication using email or username
class CustomBackend(ModelBackend): # requires to define two functions authenticate and get_user
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
# below line gives query set,you can change the queryset as per your requirement
user = UserModel.objects.filter(
Q(username__iexact=username) |
Q(email__iexact=username)
).distinct()
except UserModel.DoesNotExist:
return None
if user.exists():
'''''' get the user object from the underlying query set,
there will only be one object since username and email
should be unique fields in your models.''''''
user_obj = user.first()
if user_obj.check_password(password):
return user_obj
return None
else:
return None
def get_user(self, user_id):
UserModel = get_user_model()
try:
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
Agregue también AUTHENTICATION_BACKENDS = (''path.to.CustomBackend'',) en settings.py
Autenticación con correo electrónico y nombre de usuario para Django 2.x
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
class EmailorUsernameModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
En settings.py, agregue la siguiente línea,
AUTHENTICATION_BACKENDS = [''appname.filename.EmailorUsernameModelBackend'']
Autenticación de correo electrónico y nombre de usuario para Django 2.X
Teniendo en cuenta que esta es una pregunta común, aquí hay una implementación personalizada que imita el github.com/django/django/blob/master/django/contrib/auth/… pero que autentica al usuario con nombre de usuario o correo electrónico, sin distinción de mayúsculas y minúsculas, manteniendo la protection contra ataques de tiempo y no autenticando a los usuarios inactivos .
from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q
class CustomBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
Siempre recuerde agregarlo a su configuración.py el backend de autenticación correcto.
from django.contrib.auth.models import User
from django.db import Q
class EmailAuthenticate(object):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = User.objects.get(Q(email=username) | Q(username=username))
except User.DoesNotExist:
return None
except MultipleObjectsReturned:
return User.objects.filter(email=username).order_by(''id'').first()
if user.check_password(password):
return user
return None
def get_user(self,user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Y luego en
settings.py
:
AUTHENTICATION_BACKENDS = (
''articles.backends.EmailAuthenticate'',
)
donde artículos es mi aplicación django,
backends.py
es el archivo python dentro de mi aplicación y
EmailAuthenticate
es la clase de autenticación de backend dentro de mi archivo
backends.py