L'utilisation de l'email comme champ de nom d'utilisateur dans Django 1.5 custom User model entraîne FieldError

Je souhaite utiliser un champ email comme champ Nom d'utilisateur pour mon modèle d'utilisateur personnalisé. J'ai le modèle utilisateur personnalisé suivant sous-classant le modèle AbstractUser de Django:

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

    USERNAME_FIELD = 'email'

Mais quand je cours

Python manage.py sql myapp

Je reçois l'erreur suivante:

FieldError: le champ Local 'email' de la classe 'CustomUser' se heurte à un champ de nom similaire de la classe de base 'AbstractUser'

La raison pour laquelle j'inclus mon propre champ email dans le premier le lieu est d'ajouter l'option unique=True. sinon, je reçois:

Myapp.customuser: le champ USERNAME_FIELD doit être unique. Ajoutez unique = True aux paramètres du champ.

Maintenant, en ce qui concerne cette: https://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted
Comment puis-je y parvenir? (autre que de nommer le champ "user_email" ou quelque chose comme ça à la place)

22
demandé sur OrPo 2013-03-24 14:09:57

4 réponses

Ian, je vous remercie beaucoup pour la réponse intelligente:)

Cependant, je me suis déjà "patché" une solution.

Puisque AbstractUser ont aussi un champ username qui est totalement inutile pour moi
J'ai décidé de créer mon "propre" AbstractUser.

En sous-classant AbstractBaseUser et PermissionsMixin je conserve la plupart des méthodes intégrées du modèle utilisateur sans ajouter de code.

J'ai également profité de cette opportunité pour créer un Manager personnalisé pour éliminer l'utilisation dans le Champ username all ensemble:

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):
          .....

Cette solution entraîne la répétition d'une partie du code intégré de Django (principalement des champs de modèle qui existent déjà dans AbstractUser tels que 'first_name', 'last_name' etc.) mais aussi dans un objet utilisateur plus propre et une table de base de données.

Il est vraiment dommage que le flexibily introduit en 1.5 avec USERNAME_FIELD ne puisse pas être utilisé pourréellement créer un modèle utilisateur flexible sous toutes les contraintes existantes.

EDIT: il y a un exemple complet travaillé disponible dans les documents officiels: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

36
répondu OrPo 2014-01-30 00:34:18

Si votre cible réelle est des valeurs "email" uniques, et en ignorant les valeurs "username", alors vous pouvez:

  • remplissez "nom d'utilisateur" avec par exemple sha256(user.email).hexdigest()[:30]
  • Ajouter unicité de cette façon:

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

Il en résulte:

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

Fonctionne comme prévu, et est assez simple.

9
répondu Denis Ryzhkov 2013-07-03 17:40:49

, Vous pouvez modifier votre CustomUser pour modifier la email champ attribut unique=True.

Ajoutez ceci à la fin de votre classe utilisateur personnalisée comme ceci:

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

Notez que nous changeons _unique et non unique parce que ce dernier est un simple @property.

C'est un hack, et j'aimerais entendre des réponses "officielles" pour résoudre ce problème.

7
répondu Ian 2013-03-24 20:50:49

Utiliser l'exemple du site officiel :

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

Voici un exemple d'application utilisateur personnalisée compatible admin. Ce modèle d'utilisateur utilise une adresse e-mail comme nom d'utilisateur et a une date de naissance requise; il ne fournit aucune vérification d'autorisation, au-delà d'un simple indicateur admin sur le compte d'utilisateur. Ce modèle serait compatible avec toutes les formes et vues auth intégrées, à l'exception de L'utilisateur les formes de la création. Cet exemple illustre comment la plupart des composants fonctionnent ensemble, mais n'est pas destiné à être copié directement dans des projets pour une utilisation en production.

2
répondu maxbellec 2014-10-24 23:48:44