¿Cuál es la mejor manera de ampliar el modelo de usuario en Django?
¿Cuál es la mejor manera de ampliar el modelo de Usuario (incluido con la aplicación de autenticación de Django) con campos personalizados? Posiblemente también me gustaría utilizar el correo electrónico como nombre de usuario (para fines de autenticación).
Ya he visto algunas formas de hacerlo, pero no puedo decidir cuál es la mejor.
La forma menos dolorosa y, de hecho, recomendada por Django de hacer esto es a través de una OneToOneField(User)
propiedad.
Ampliando el modelo de usuario existente
…
Si desea almacenar información relacionada con
User
, puede utilizar una relación uno a uno con un modelo que contenga los campos para obtener información adicional. Este modelo uno a uno a menudo se denomina modelo de perfil, ya que podría almacenar información no relacionada con la autenticación sobre un usuario del sitio.
Dicho esto, ampliarlo django.contrib.auth.models.User
y sustituirlo también funciona...
Sustituir un modelo de usuario personalizado
Algunos tipos de proyectos pueden tener requisitos de autenticación para los cuales el modelo integrado de Django
User
no siempre es apropiado. Por ejemplo, en algunos sitios tiene más sentido utilizar una dirección de correo electrónico como token de identificación en lugar de un nombre de usuario.[Ed: Siguen dos advertencias y una notificación , mencionando que esto es bastante drástico .]
Definitivamente me mantendría alejado de cambiar la clase de Usuario real en su árbol fuente de Django y/o copiar y alterar el módulo de autenticación.
Nota: esta respuesta está en desuso. vea otras respuestas si está utilizando Django 1.7 o posterior.
Así es como lo hago.
#in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
#other fields here
def __str__(self):
return "%s's profile" % self.user
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'
Esto creará un perfil de usuario cada vez que se guarde un usuario, si se crea. Luego puedes usar
user.get_profile().whatever
Aquí hay más información de los documentos.
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
Actualización: tenga en cuenta que AUTH_PROFILE_MODULE
está en desuso desde la versión 1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module
Bueno, ha pasado algún tiempo desde 2008 y es hora de encontrar una nueva respuesta. Desde Django 1.5 podrás crear una clase de usuario personalizada. En realidad, en el momento en que escribo esto, ya está fusionado con el maestro, así que puedes probarlo.
Hay información al respecto en los documentos o, si desea profundizar más, en este compromiso .
Todo lo que tiene que hacer es agregar AUTH_USER_MODEL
a la configuración la ruta a la clase de usuario personalizada, que se extiende AbstractBaseUser
(versión más personalizable) o AbstractUser
(clase de usuario más o menos antigua que puede extender).
Para las personas a las que les da pereza hacer clic, aquí hay un ejemplo de código (tomado de docs ):
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
u = self.create_user(username,
password=password,
date_of_birth=date_of_birth
)
u.is_admin = True
u.save(using=self._db)
return u
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Desde Django 1.5, puedes ampliar fácilmente el modelo de usuario y mantener una única tabla en la base de datos.
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
class UserProfile(AbstractUser):
age = models.PositiveIntegerField(_("age"))
También debe configurarlo como clase de usuario actual en su archivo de configuración.
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"
Si desea agregar muchas preferencias de usuarios, la opción OneToOneField puede ser una mejor opción.
Una nota para las personas que desarrollan bibliotecas de terceros: si necesitan acceder a la clase de usuario, recuerden que las personas pueden cambiarla. Utilice el ayudante oficial para obtener la clase correcta
from django.contrib.auth import get_user_model
User = get_user_model()