En múltiples ocasiones nos gustaría extender el modelo User para que incluyera otros campos y funciones. La manera "oficial" de hacer esto (la mostrada en la documentación de Django) es creando un modelo para el perfil de usuario que incluya un campo con una ForeignKey apuntando a la clase User. Vamos a ver cómo se puede hacer de la forma oficial, con herencia y utilizando un método alternativo añadiendo atributos a la clase User con add_to_class.
from django.contrib.auth.models import User
class Perfil(models.Model):
user = models.ForeignKey(User, unique=True)
direccion = models.CharField(max_length=250, blank=True)
telefono = models.PositiveIntegerField(null=True, blank=True)
Utilizamos unique=True en el campo user para asegurarnos de que sólo pueda haber un único perfil por cada usuario. Luego añadimos AUTH_PROFILE_MODULE a nuestro archivo settings.py:
AUTH_PROFILE_MODULE = 'mi_aplicacion.Perfil'
A partir de ese momento podemos acceder al perfil del usuario con user.get_profile(). Esta es la forma "oficial" de hacerlo pero presenta desventajas: Algunos atributos del usuario se acceden como user.atributo y otros como user.get_profile().atributo. Y esto se complica más aún cuando tenemos que establecer relaciones entre usuarios: ¿Ponemos la relación entre perfiles? ¿Entre Perfil y User? Generalmente es recomendable que la relación sea entre perfiles:
from django.contrib.auth.models import User
class Perfil(models.Model):
user = models.ForeignKey(User, unique=True)
direccion = models.CharField(max_length=250, blank=True)
telefono = models.PositiveIntegerField(null=True, blank=True)
amigos = models.ManyToManyField('self', symmetrical=True, blank=True)
Aún así resulta molesto tener que acceder a los amigos de un usuario de esta manera:
for perfil in user.get_profile().amigos:
print perfil.user # mostrar el usuario
Nos gustaría que fuese tan sencillo como:
for usuario in user.amigos:
print usuario
Otra forma de hacerlo es creando una clase que herede de la clase User:
from django.contrib.auth.models import User
class Usuario(User):
direccion = models.CharField(max_length=250, blank=True)
telefono = models.PositiveIntegerField(null=True, blank=True)
amigos = models.ManyToManyField('self', symmetrical=True, blank=True)
De esta manera el problema se nos presenta al no poder acceder directamente a los datos del perfil con request.user en nuestras vistas.
Vamos a ver un método menos "limpio" que los anteriores pero más eficiente. Se trata de añadir atributos y métodos a la clase User antes de haber creado la tabla de usuario mediante el comando syncdb. En el models.py de cualquier aplicación del proyecto importamos la clase User y utilizamos add_to_class para añadir los atributos y las funciones que queramos a la clase User antes de crear su correspondiente tabla en la base de datos:
from django.contrib.auth.models import User
User.add_to_class('direccion', models.FloatField(null=True,blank=True))
User.add_to_class('telefono', models.PositiveIntegerField(null=True,blank=True))
User.add_to_class('amigos', models.ManyToManyField('self', symmetrical=True, blank=True))
Ya podemos acceder a todos los atributos del usuario mediante user.atributo (p. ej: user.telefono). Crear un método propio para la clase User es igual de sencillo:
def es_popular(self):
# devuelve True si tiene más de 100 amigos
if self.amigos.all.count() > 100:
return True
else:
return False
User.add_to_class('es_popular', es_popular)
# ahora podemos acceder al método mediante user.es_popular()
Ventajas de este método:
Se crea una única tabla para el usuario y su perfil: Esto es más eficiente si en las vistas vamos a necesitar información del usuario e información de su perfil constantemente. Con este método también podemos extender la clase User con métodos propios, y accedemos a todos los atributos del usuario mediante user.atributo.
Importante: Al crear un usuario deberás dar un valor siempre a los campos del perfil que no permitan valores nulos.
Publicado por Antonio Melé el Thursday 27 de November de 2008
Compártelo:
| Categorías:
auth,
modelos,
trucos
Algo interesante que nos aporta django-command-extensions es poder crear una representación gráfica de nuestros modelos (o por decirlo de otro modo nuestro esquema de ...
Actualización/Update: Zack translated this post into english and it is available here.
A veces tenemos que modificar información relativa a dos o más ...
Cuando usamos un campo con diferentes opciones (choices) en nuestro modelo utilizamos una lista de elementos cada uno con el valor real que se ...
Tras ver que la mayoría de los proyectos existentes para generar miniaturas de imágenes aún no funcionan con la API de Storage y que ...
No hay ningún comentario todavía.
Suscríbete a nuestro feed RSS y al feed de la comunidad para estar al tanto de todo lo que ocurre entorno a Django.
Tú también puedes escribir en éste blog. Para hacerlo basta con que nos digas sobre qué quieres escribir un artículo relacionado con Django.
Utilizar un formulario para modificar 2 modelos
Descubriendo objetos similares por sus etiquetas