2015-07-12 11 views
6

mio personalizzato modello di utente:USERNAME_FIELD multipli in Django utente modello

class MyUser(AbstractBaseUser): 
    username = models.CharField(unique=True,max_length=30) 
    email = models.EmailField(unique=True,max_length=75) 
    is_staff = models.IntegerField(default=False) 
    is_active = models.IntegerField(default=False) 
    date_joined = models.DateTimeField(default=None) 

    # Use default usermanager 
    objects = UserManager() 

    USERNAME_FIELD = 'email' 

C'è un modo per specificare USERNAME_FIELD multipla? Qualcosa come ['email','username'] in modo che gli utenti possano accedere via e-mail e nome utente?

risposta

6

L'impostazione USERNAME_FIELD non supporta un elenco. Puoi creare un custom authentication backend che cerca di cercare l'utente nei campi "email" o "username".

from django.db.models import Q 

class UsernameOrEmailBackend(object): 
    def authenticate(self, username=None, password=None, **kwargs): 
     try: 
      # Try to fetch the user by searching the username or email field 
      user = MyUser.objects.get(Q(username=username)|Q(email=username)) 
      if user.check_password(password): 
       return user 
     except MyUser.DoesNotExist: 
      # Run the default password hasher once to reduce the timing 
      # difference between an existing and a non-existing user (#20760). 
      MyUser().set_password(password) 

Poi, nel vostro settings.py impostare AUTHENTICATION_BACKENDS al backend di autenticazione:

AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\ 

Si noti che questa soluzione non è perfetta. Ad esempio, il ripristino della password funzionerà solo con il campo specificato nell'impostazione USERNAME_FIELD.

0

Sfortunatamente, non immediatamente disponibile.

Il modulo auth auth asserisce che il valore USERNAME_FIELD è monovalore.

Vedi https://github.com/django/django/search?q=USERNAME_FIELD

Se si vuole avere un USERNAME_FIELD più valori, si sia necessario scrivere la logica corrispondente o per trovare un pacchetto che consente.

2

No, non è possibile avere più di un campo definito in USERNAME_FIELD.

Un'opzione sarebbe scrivere il proprio login personalizzato per verificare entrambi i campi. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/

Ad esempio, cambiare il back-end al proprio. AUTHENTICATION_BACKENDS quindi scrivere un metodo di autenticazione e controllare il nome utente su entrambi i campi nel DB.

PS si consiglia di utilizzare unique_together sul modello in modo da non incorrere in problemi.

Un'altra opzione potrebbe essere quella di utilizzare il campo effettivo username per memorizzare sia la stringa che l'e-mail.

6

Possiamo farlo implementando il nostro backend di autenticazione Email.

Si può fare qualcosa di simile di seguito:

Step-1 Substite il modello utente personalizzata nelle impostazioni:

Dal momento che non sarebbe utilizzando il modello predefinito User di Django per l'autenticazione, è necessario definire il nostro modello personalizzato MyUser in settings.py. Specificare MyUser come AUTH_USER_MODEL nelle impostazioni del progetto.

AUTH_USER_MODEL = 'myapp.MyUser' 

Step-2 Scrivi la logica per il backend di autenticazione personalizzato:

a scrivere le nostre backend di autenticazione, abbiamo bisogno di implementare atleast due metodi cioè get_user(user_id) e authenticate(**credentials).

from django.contrib.auth import get_user_model 
from django.contrib.auth.models import check_password 

class MyEmailBackend(object): 
    """ 
    Custom Email Backend to perform authentication via email 
    """ 
    def authenticate(self, username=None, password=None): 
     my_user_model = get_user_model() 
     try: 
      user = my_user_model.objects.get(email=username) 
      if user.check_password(password): 
       return user # return user on valid credentials 
     except my_user_model.DoesNotExist: 
      return None # return None if custom user model does not exist 
     except: 
      return None # return None in case of other exceptions 

    def get_user(self, user_id): 
     my_user_model = get_user_model() 
     try: 
      return my_user_model.objects.get(pk=user_id) 
     except my_user_model.DoesNotExist: 
      return None 

Step-3 Specificare l'autenticazione back-end personalizzato nelle impostazioni:

Dopo aver scritto l'autenticazione back-end personalizzato, specificare questo backend di autenticazione nell'impostazione AUTHENTICATION_BACKENDS.

AUTHENTICATION_BACKENDS contiene l'elenco dei back-end di autenticazione da utilizzare. Django prova ad autenticare attraverso tutti i suoi backend di autenticazione. Se il primo metodo di autenticazione fallisce, Django tenta il secondo, e così via, fino a quando tutti i backend sono stati tentati.

AUTHENTICATION_BACKENDS = (
    'my_app.backends.MyEmailBackend', # our custom authentication backend 
    'django.contrib.auth.backends.ModelBackend' # fallback to default authentication backend if first fails 
    ) 

Se l'autenticazione tramite MyEmailBackend non riesce utente cioè non poteva essere autenticati via email, allora usiamo l'autenticazione di default del Django ModelBackend che cercherà di autenticarsi tramite username campo della MyUser modello.

+0

Ho creato un back-end di autenticazione personalizzato simile ora voglio passare i campi di posta elettronica e numero di telefono anche mentre eseguo l'accesso a questo metodo. Ma ottengo solo il nome utente e il campo password kwargs è vuoto Qualsiasi idea come ottenere tutti i campi? – Kishan

+0

Puoi pubblicare il codice di esempio che stai provando? –

0

Se l'USERNAME_FIELD è username e l'utente accede con email, forse si può scrivere un codice che recupera il username utilizzando l'apposita email e quindi utilizzare tale username insieme al password per autenticare.

Problemi correlati