2015-07-12 4 views
6

Mein individuelles Benutzermodell:Multiple USERNAME_FIELD in django Benutzermodell

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' 

Gibt es eine Möglichkeit, mehr USERNAME_FIELD angeben? Etwas wie ['email','username'], so dass Benutzer sich per E-Mail sowie Benutzernamen anmelden können?

Antwort

6

Die Einstellung USERNAME_FIELD unterstützt keine Liste. Sie könnten eine custom authentication backend erstellen, die versucht, den Benutzer in den Feldern "E-Mail" oder "Benutzername" nachzuschlagen.

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) 

Dann in Ihrem settings.py gesetzt AUTHENTICATION_BACKENDS auf Ihre Authentifizierungs-Backend:

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

Beachten Sie, dass diese Lösung nicht perfekt ist. Zum Beispiel funktioniert das Zurücksetzen von Kennwörtern nur mit dem in Ihrer Einstellung USERNAME_FIELD angegebenen Feld.

0

Leider nicht out-of-the-box.

Das Auth-Contrib-Modul bestätigt, dass der USERNAME_FIELD-Wert monovalent ist.

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

Wenn Sie ein mehrwertiges USERNAME_FIELD haben wollen, müssen Sie entweder die entsprechende Logik zu schreiben oder ein Paket zu finden, die es erlauben.

2

Nein, Sie können nicht mehr als ein Feld in USERNAME_FIELD definiert haben.

Eine Möglichkeit wäre, Ihre eigene benutzerdefinierte Anmeldung zu schreiben, um selbst nach beiden Feldern zu suchen. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/

d. H. Ändern Sie das Back-End zu Ihrem eigenen. AUTHENTICATION_BACKENDS Schreiben Sie dann eine Authentifizierungsmethode und überprüfen Sie den Benutzernamen in beiden Feldern in der DB.

PS möchten Sie möglicherweise unique_together auf Ihrem Modell verwenden, so dass Sie nicht auf Probleme stoßen.

Eine andere Option wäre, das tatsächliche Feld username zu verwenden, um sowohl Zeichenfolge als auch E-Mail zu speichern.

6

Wir können dies tun, indem wir unser eigenes Email-Authentifizierungs-Backend implementieren.

Sie können wie unten etwas tun:

Step-1 Substite die benutzerdefinierte User-Modell in den Einstellungen:

Da wir nicht für die Authentifizierung Djangos Standard User Modell würde verwenden, müssen wir definieren unsere Gewohnheit MyUser Modell in settings.py. Geben Sie in den Projekteinstellungen MyUser als AUTH_USER_MODEL an.

AUTH_USER_MODEL = 'myapp.MyUser' 

Step-2, die Logik für den benutzerdefinierten Authentifizierungs-Backend schreiben:

eigenen Authentifizierungs-Backend zu schreiben, müssen wir atleast zwei Methoden heißt get_user(user_id) und authenticate(**credentials) implementieren.

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 Geben Sie den benutzerdefinierten Authentifizierungs-Backend in Einstellungen:

Nach der benutzerdefinierten Authentifizierung backend Schreiben spezifizieren diese Authentifizierungs-Backend im AUTHENTICATION_BACKENDS Einstellung.

AUTHENTICATION_BACKENDS enthält die Liste der zu verwendenden Authentifizierungs-Backends. Django versucht sich über alle Authentifizierungs-Backends hinweg zu authentifizieren. Wenn die erste Authentifizierungsmethode fehlschlägt, versucht Django die zweite und so weiter, bis alle Backends versucht wurden.

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

Wenn die Authentifizierung per MyEmailBackend d.h Benutzer nicht nicht über email authentifiziert werden kann, dann verwenden wir den Standard-Authentifizierung ModelBackend des Django, die über username Feld MyUser Modell werden versuchen, zu authentifizieren.

+0

Ich erstellte ähnliche benutzerdefinierte Authentifizierung Backend jetzt möchte ich E-Mail und Telefonnummer Felder auch während der Anmeldung in diese Methode. Aber ich bekomme nur Benutzername und Passwort Feld kwargs ist leer Irgendeine Idee, wie man alle Felder bekommt? – Kishan

+0

Können Sie den Beispielcode posten, den Sie versuchen? –

0

Wenn Ihr USERNAME_FIELD username ist und der Benutzer meldet sich mit email, vielleicht können Sie einen Code schreiben, der die username mit der email und dann zur Verfügung gestellt holt verwenden, dass username zusammen mit dem password zu authentifizieren.

Verwandte Themen