Django – Accedi con l’email

Voglio che django autentifichi gli utenti via e-mail, non tramite i nomi utente. Un modo può fornire il valore email come valore del nome utente, ma non lo voglio. Essendo il motivo, ho un URL /profile// , quindi non posso avere un URL /profile/[email protected]/ .

Un altro motivo è che tutte le e-mail sono uniche, ma a volte capita che il nome utente sia già stato preso. Quindi sto creando automaticamente il nome utente come fullName_ID .

Come posso semplicemente fare in modo che Django si autentichi con la posta elettronica?

Questo è il modo in cui creo un utente.

 username = `abcd28` user_email = `[email protected]` user = User.objects.create_user(username, user_email, user_pass) 

Questo è il modo in cui accedo.

 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) 

C’è qualche altro di accesso oltre a ottenere il nome utente prima?

Dovresti scrivere un backend di autenticazione personalizzato. Qualcosa del genere funzionerà:

 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 

Quindi, imposta il back-end come back-end di autenticazione nelle tue impostazioni:

 AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend'] 

Aggiornato Eredita da ModelBackend quando implementa già metodi come get_user() .

Se stai iniziando un nuovo progetto, django ti consiglia vivamente di impostare un modello utente personalizzato. (consultare https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project )

e se l’hai fatto, aggiungi tre linee al tuo modello utente:

 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 

Quindi authenticate(email=email, password=password) funziona, mentre l’ authenticate(username=username, password=password) smette di funzionare.

Avevo un requisito simile in cui il nome utente / email dovrebbe funzionare per il campo del nome utente. Nel caso in cui qualcuno stia cercando il modo di backend di autenticazione, controlla il seguente codice di lavoro. Puoi cambiare il set di query se desideri solo l’email.

 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 

Aggiungi anche AUTHENTICATION_BACKENDS = (‘path.to.CustomBackend’,) in settings.py

È necessario personalizzare la class ModelBackend. Il mio codice semplice:

 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 

E nel file settings.py , aggiungi:

 AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']