2013-03-24 3 views
21

Ich möchte ein E-Mail-Feld als Benutzername Feld für mein benutzerdefiniertes Benutzermodell verwenden. Ich habe folgendes benutzerdefinierte User-Modell Subklassen Djangos AbstractUser Modell:Verwenden von E-Mail als Benutzername Feld in Django 1.5 benutzerdefinierte Benutzermodell Ergebnisse in Feldfehler

class CustomUser(AbstractUser): 
    .... 
    email = models.EmailField(max_length=255, unique=True) 

    USERNAME_FIELD = 'email' 

Aber wenn ich

python manage.py sql myapp

laufen bekomme ich folgende Fehlermeldung:

FieldError: Local field 'email' in class 'CustomUser' clashes with field of similar name from base class 'AbstractUser'

Der Grund, warum ich meine eigenen umfassen E-Mail-Feld an erster Stelle ist die Option unique=True zu ihm hinzuzufügen. sonst bekomme ich:

myapp.customuser: The USERNAME_FIELD must be unique. Add unique=True to the field parameters.

nun in Bezug auf diese: https://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted
Wie kann ich das erreichen? (Anderenfalls benennen Sie das Feld "user_email" oder etwas ähnliches)

Antwort

34

Ian, ich danke Ihnen sehr für die clevere Antwort :)

Allerdings habe ich mich schon eine Lösung „geflickt“.

Seit AbstractUser haben auch ein username Feld, das für mich total unnötig ist
ich beschlossen, meine „eigenen“ AbstractUser zu erstellen.

Durch die Unterklassen AbstractBaseUser und PermissionsMixin behalte ich die meisten der integrierten Benutzermodell-Methoden, ohne Code hinzuzufügen.

ich nutzte diese Gelegenheit, eine Gewohnheit zu schaffen Manager die Verwendung in username Feld zu beseitigen alle zusammen:

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager 

class CustomUser(AbstractBaseUser, PermissionsMixin): 
    .... 
    email = models.EmailField(max_length=255, unique=True) 
    first_name = ... 
    last_name = ... 
    is_active = ... 
    is_staff = ... 
    .... 

    objects = CustomUserManager() 

    USERNAME_FIELD = 'email' 


class CustomUserManager(BaseUserManager): 
    def create_user(self, email, password=None, **extra_fields): 
      ..... 

    def create_superuser(self, email, password, **extra_fields): 
      ..... 

Diese Lösung in Wiederholung von integriertem Code sind einige von Django führt (hauptsächlich Modell Felder, die bereits in AbstractUser wie 'first_name', 'last_name' usw. vorhanden sind, aber auch in einer saubereren Benutzerobjekt- und Datenbanktabelle.

Es ist wirklich schade, dass die flexibily in 1.5 mit USERNAME_FIELD eingeführt wird, kann nicht auf actualy verwendet werden unter allen bestehenden Constraints ein flexibles User-Modell erstellen.

EDIT: Es gibt ein umfassendes Beispiel arbeitete in den offiziellen Dokumenten: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

+0

Was macht Ihr create_superuser Methode enthalten? – Siecje

+0

Erzeugt ein Benutzerobjekt ohne 'username' Feld (stattdessen' email') mit create_user: 'u = self.create_user (email, Passwort, ** extra_fields)', setzt den Superuser "spezielle" Felder ('is_staff, is_superuser, ... ') und speichert dann diesen Benutzer. – OrPo

+0

ist die Implementierung von 'CustomUserMananger' ein Muss oder kann ich es überspringen und die Django-Mitarbeiter werden nicht mehr eingestellt? – andi

7

Sie können Ihre CustomUser bearbeiten, um das email Feldattribut zu unique=True zu ändern.

bis zum Ende Ihrer benutzerdefinierten Benutzerklasse Fügen Sie diese wie folgt:

class CustomUser(AbstractUser): 
    ... 
    USERNAME_FIELD = 'email' 
    ... 
CustomUser._meta.get_field_by_name('email')[0]._unique=True 

Bitte beachte, dass wir _unique und nicht unique weil letztere ist eine einfache @property sind zu ändern.

Dies ist ein Hack, und ich würde gerne "offizielle" Antworten hören, um dies zu lösen.

8

Wenn Ihr eigentliches Ziel einzigartiger „E-Mail“ Wert ist, und „username“ Werte zu ignorieren, dann können Sie:

  • Füllen Sie "Benutzername" mit zB sha256(user.email).hexdigest()[:30]
  • Einzigartigkeit auf diese Weise hinzufügen:

    class User(AbstractUser): 
        class Meta: 
         unique_together = ('email',) 
    

Daraus ergibt sich:

CREATE TABLE "myapp_user" (
    ... 
    "email" varchar(75) NOT NULL, 
    UNIQUE ("email") 
) 

funktioniert genauso wie erwartet, und ist ziemlich einfach.

+0

Dies war die beste Option, die ich im Umgang mit dieser Angelegenheit gesehen habe. Danke vielmals! – Emilcasvi

2

Verwenden Sie das Beispiel von der offiziellen Website:

https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#a-full-example

Here is an example of an admin-compliant custom user app. This user model uses an email address as the username, and has a required date of birth; it provides no permission checking, beyond a simple admin flag on the user account. This model would be compatible with all the built-in auth forms and views, except for the User creation forms. This example illustrates how most of the components work together, but is not intended to be copied directly into projects for production use.

+0

Danke für die Hinweise auf die Dokumente! – user1496984

+0

Dies ist eigentlich der Weg zu gehen – danigosa

+1

Ist all das wirklich notwendig, nur um das USERNAME_FIELD zu ändern? –