Pregunta

¿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 un pocos maneras hacerlo, pero no puedo decidir cuál es el mejor.

¿Fue útil?

Solución

La forma menos dolorosa y, de hecho, recomendada por Django de hacer esto es a través de un OneToOneField(User) propiedad.

Ampliando el modelo de usuario existente

Si desea almacenar información relacionada con User, puedes usar un relación uno a uno a un modelo que contiene 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, extendiendo django.contrib.auth.models.User y suplantarlo también sirve...

Sustituir un modelo de usuario personalizado

Algunos tipos de proyectos pueden tener requisitos de autenticación para los cuales la función integrada de Django User El modelo no siempre es el adecuado.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.

Otros consejos

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

Actualizar: Tenga en cuenta que AUTH_PROFILE_MODULE está en desuso desde v1.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 alguna información al respecto en documentos o si quieres profundizar más en ello, en este compromiso.

Todo lo que tienes que hacer es agregar AUTH_USER_MODEL a la configuración con 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 puedes ampliar).

Para las personas a las que les da pereza hacer clic, aquí hay un ejemplo de código (tomado de documentos):

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 necesita acceder a la clase de usuario, recuerde 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()

Hay una recomendación oficial sobre almacenar información adicional sobre los usuarios.El Libro Django también analiza este problema en la sección Perfiles.

El siguiente es otro método para ampliar un usuario.Siento que es más claro, fácil y legible que los dos enfoques anteriores.

http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

Usando el enfoque anterior:

  1. no necesitas usarusuario.get_profile().nuevo atributo Para acceder a la información adicional relacionada con el usuario
  2. puede acceder directamente a los nuevos atributos adicionales a través deusuario.nuevo atributo

Puede simplemente ampliar el perfil de usuario creando una nueva entrada cada vez que se crea un usuario mediante el uso de señales de guardado posterior de Django.

modelos.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User, related_name='profile')
    city = models.CharField(max_length=100, null=True)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

def create_user_profile(sender, instance, created, **kwargs):
    if created:
    userProfile.objects.create(userName=instance)

post_save.connect(create_user_profile, sender=User)

Esto creará automáticamente una instancia de empleado cuando se cree un nuevo usuario.

Si desea ampliar el modelo de usuario y desea agregar más información mientras crea el usuario, puede usar django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html).Esto creará un formulario para agregar usuarios con todos los campos definidos en el modelo userProfile.

modelos.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User)
    city = models.CharField(max_length=100)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

formularios.py

from django import forms
from django.forms import ModelForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
from .models import *

class profileForm(ModelForm):

    class Meta:
        model = Employee
        exclude = ('userName',)


class addUserMultiForm(MultiModelForm):
    form_classes = {
        'user':UserCreationForm,
        'profile':profileForm,
    }

vistas.py

from django.shortcuts import redirect
from .models import *
from .forms import *
from django.views.generic import CreateView

class addUser(CreateView):
    form_class = addUserMultiForm
    template_name = "addUser.html"
    success_url = '/your url after user created'

    def form_valid(self, form):
        user = form['user'].save()
        profile = form['profile'].save(commit=False)
        profile.userName = User.objects.get(username= user.username)
        profile.save()
        return redirect(self.success_url)

agregarUsuario.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="." method="post">
            {% csrf_token %}
            {{ form }}     
            <button type="submit">Add</button>
        </form>
     </body>
</html>

URL.py

from django.conf.urls import url, include
from appName.views import *
urlpatterns = [
        url(r'^add-user/$', addUser.as_view(), name='addDistributor'),
]

Ampliando el modelo de usuario de Django (UserProfile) como un profesional

He encontrado esto muy útil: enlace

Un extracto:

desde django.contrib.auth.models importar usuario

class Employee(models.Model):
    user = models.OneToOneField(User)
    department = models.CharField(max_length=100)

>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

Como novedad en Django 1.5, ahora puede crear su propio modelo de usuario personalizado (lo que parece ser una buena opción en el caso anterior).Referirse a 'Personalizar la autenticación en Django'

Probablemente la característica nueva más interesante de la versión 1.5.

Esto es lo que hago y, en mi opinión, es la forma más sencilla de hacerlo.Defina un administrador de objetos para su nuevo modelo personalizado y luego defina su modelo.

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

class User_manager(BaseUserManager):
    def create_user(self, username, email, gender, nickname, password):
        email = self.normalize_email(email)
        user = self.model(username=username, email=email, gender=gender, nickname=nickname)
        user.set_password(password)
        user.save(using=self.db)
        return user

    def create_superuser(self, username, email, gender, password, nickname=None):
        user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)
        user.is_superuser = True
        user.is_staff = True
        user.save()
        return user



  class User(PermissionsMixin, AbstractBaseUser):
    username = models.CharField(max_length=32, unique=True, )
    email = models.EmailField(max_length=32)
    gender_choices = [("M", "Male"), ("F", "Female"), ("O", "Others")]
    gender = models.CharField(choices=gender_choices, default="M", max_length=1)
    nickname = models.CharField(max_length=32, blank=True, null=True)

    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    REQUIRED_FIELDS = ["email", "gender"]
    USERNAME_FIELD = "username"
    objects = User_manager()

    def __str__(self):
        return self.username

No olvides agregar esta línea de código en tu settings.py:

AUTH_USER_MODEL = 'YourApp.User'

Esto es lo que hago y siempre funciona.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top