arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

¿Cómo personalizar el modelo User en Django?

Eduardo Ismael Garcia

Full Stack Developer at Código Facilito.

av_timer 3 Min. de lectura

remove_red_eye 47401 visitas

calendar_today 01 Julio 2019

Como sabemos Django nos provee de un sistema de autenticación basado en su modelo User. El modelo fue construido para solventar los problemas más comunes al momentos al momento de trabajar con usuarios en la web. Sin embargo, hay ocasiones en las cuales tengamos necesidades que dicho modelo no pueda solventar, en esos caso será necesario implementar otro tipo de estrategias para llegar al resultado deseado. Es por ello que en esta ocasión me gustaría compartir con ustedes 3 formas en las cuales podemos extender funcionalidades y atributos al modelo User de Django. Es algo, relativamente sencillo.

Bien, una vez dicho esto, comencemos.

Proxy model

Si lo que deseamos es agregar funcionalidad algún modelo, en este caso User, la forma más sencilla de hacerlo es mediante un proxy model.

En términos simple un proxy model no es más que un modelo el cual hereda de otro. La principal diferencia con un modelo convencional es que los proxy model no generan tablas nuevas en la base de datos.

Les comparto un webinar, donde Angie, nuestra tutora de Django, no explica el tema de Proxy model más en detalle.

from django.contrib.auth.models import User

class Customer(User):
    class Meta:
        proxy = True

    def say_hello(self):
        return "Hello, my name is {}".format(self.first_name)

En este caso al nuestro Proxy model, customer, heredar de User, este posee acceso a los atributos y métodos de su clase padre.

El método say_hello unica y exclusivamente podrá ser ejecutado por una instancia de Customer.

customer = Customer.objects.last()
customer.say_hello()

Para nosotros obtener un objeto customer lo haríamos de la misma manera que si quisiéramos obtener un objeto User.

#1
user = User.objects.get(pk=1)
user.say_hello() #Error

#2
customer = Customer.objects.get(pk=1)
customer.say_hello()
>>> Eduardo

En nuestro ejemplo, ambas consultas retornarán al mismo usuario. La principal diferencia es que la consulta número uno retorna un objeto User, y la segunda un objeto Customer, el cual, debería poseer más funcionalidades que la primera.

Relación uno a uno

Si tenemos la necesidad de agregar nuevos campos y atributos sobre nuestro modelo User, una muy buena idea es generar una relación uno a uno con un nuevo modelo.

from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()

En este caso el modelo Profile posee todos aquellos atributos que no cuenta el modelo User, atributos que serán necesarios para nuestra lógica de negocio.

user = User.objects.last()
profile = Profile.objects.create(user=user, bio='sin biografía por el momento')

Como la relación es uno a uno, ambos objetos podrán acceder a dicha relación.

user.profile.bio
profile.user.username

Si queremos agregar funcionalidad, simplemente nos apoyamos de la relación.

class Profile(models.Model):
    ...

    def say_hello(self):
        return "Hello, my name is {}".format(self.user.first_name)

Reemplazar todo

Si por alguna razón el uso de Proxy model o la relación uno a uno no son suficientes para solventar tus necesidad, pues bien, no queda de otra que sobre escribir por completo el modelo User.

Para crear nuestro propio modelo User debemos apoyarnos de la clase AbstractUser o AbstractBaseUser.

Las principal diferencia entre estas dos clases son los atributos que poseen. Para la clase AbstractBaseUser únicamente tendremos 3 atributos:

  • id
  • password
  • last_login

Por otro lado, la clase AbstractUser poseerá los siguientes atributos:

  • username
  • first_name
  • last_name
  • email
  • password
  • groups
  • user_permissions
  • is_staff
  • is_active
  • is_superuser
  • last_login
  • date_joined

Yo de forma personal recomiendo utilizar la clase AbstractUser ya que son menos las modificaciones que haremos al framework.

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    customer_id = models.CharField(max_length=100, blank=True, null=True)

    def say_hello(self):
        return "Hello, my name is {}".format(self.first_name)

Una vez creamos nuestro propio modelo User, el siguiente paso es registrarlo en el administrador.

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User

admin.site.register(User, UserAdmin)

Para que todas las funcionalidades de autenticación sigan funcionando, login, logout, request.user, los decoradores de autenticación, UserMixin etc... será necesario modificar la constante AUTH_USER_MODEL del archito settings.py.

AUTH_USER_MODEL = 'profiles.User'

Colocamos nuestra aplicación punto y nuestro nuevo modelo.

Una vez hecho esto, dejaremos de utilizar el User de Django por el nuestro.

# from django.contrib.auth.models import User

from profiles.models import User #Nuestro modelo

Trabajaremos nuestro modelo tal y como si del modelo User de Django se tratase.

from profiles.models import User

user = User.objects.create_user('username', 'eduardocodigofacilito.com', 'password')

last = User.objects.last()

first = User.objects.get(pk=1)

De igual forma, si queremos hacer referencia a nuestro modelo podemos apoyarnos de la constante AUTH_USER_MODEL.

from django.conf import settings

class Cart(models.Model):
   user = models.ForeignKey(
                settings.AUTH_USER_MODEL,
                null=True, blank=True, on_delete=models.CASCADE)

Conclusión

Estas son algunas formas en las cuales podemos extender el modelo User que Django ya nos provee, ya sea agregando nuevas funcionalidades, en forma de métodos o nuevos atributos.

De forma personal creo que la mejor manera de tener un modelo User flexible es creando el nuestro, apoyándonos de la clase AbstractUser. Por supuesto, todo depende de nuestras necesidades. 🌯😃