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 Jueves 27 de Noviembre 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 ...
A veces queremos utilizar la función de aggregación annotate() y aplicar filtros al modelo que se encuentra dentro de la misma, pero no es ...
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