Cómo hacer un gestor de objetos en Django

Archivada en Desarrollo

Cómo hacer un gestor de objetos en Django

Como recordarán en el artículo anterior vimos como crear un modelo de usuario con algunas características agregadas al modelo estándar de Django.

Cuando sustituímos el modelo User por uno creado a nuestras necesidades, debemos definir un gestor relacionado, es decir una clase Manager que sobreescriba las funciones de create_user y create_superuser.

Dentro del archivo nucleo/models.py, agregamos el siguiente código, antes de la clase Pipol.

from django.contrib.auth.models import BaseUserManager

class PipolManager(BaseUserManager):
    def create_user(self, email, password=None, **kwargs):
        if not email:
            raise ValueError(
                'Los usuarios deben tener una dirección de correo válida.'
            )

        if not kwargs.get('username'):
            raise ValueError(
                'Los usuarios deben tener un nombre de usuario válido.'
            )

        if not kwargs.get('entidad'):
            raise ValueError('Debe seleccionar una entidad.')

        if not kwargs.get('sitio'):
            raise ValueError('Debe seleccionar una junta.')

        if not kwargs.get('puesto'):
            raise ValueError('Debe seleccionar un puesto.')

        pipol = self.model(
            email=self.normalize_email(email), username=kwargs.get('username')
        )

        pipol.set_password(password)
        pipol.save()

        return pipol

    def create_superuser(self, email, password, **kwargs):
        pipol = self.create_user(email, password, **kwargs)

        pipol.is_admin = True
        pipol.save()

        return pipol

Ahora analizaremos esta clase línea por línea.

        if not email:
            raise ValueError(
                'Los usuarios deben tener una dirección de correo válida.'
            )

        if not kwargs.get('username'):
            raise ValueError(
                'Los usuarios deben tener un nombre de usuario válido.'
            )

Ya que se requiere que los usuarios tengan un correo y un nombre de usuario, debemos lanzar un error si falta alguno de estos atributos.

        if not kwargs.get('entidad'):
            raise ValueError('Debe seleccionar una entidad.')

        if not kwargs.get('sitio'):
            raise ValueError('Debe seleccionar una junta.')

        if not kwargs.get('puesto'):
            raise ValueError('Debe seleccionar un puesto.')

Y ya que definimos que la entidad, el sitio y el puesto son obligarios, lanzamos errores cuando no se definen estos valores.

        pipol = self.model(
            email=self.normalize_email(email), username=kwargs.get('username')
        )

También debemos definir el modelo para la clase PipolManager, usando self.model que se refiere al modelo definido en BaseUserManager de forma predeteriminada. Este comportamiento estándar está definido en settings.AUTH_USER_MODEL, el cual cambiaremos en un momento, más adelante.

        pipol = self.create_user(email, password, **kwargs)

        pipol.is_admin = True
        pipol.save()

Para no violar el principio DRY1 de Django, para crear al administrador con create_superuser, simplemente dejamos que create_user se encargue de esta función y libera a create_superuser que solo se ocupa de marcar un objeto Pipol como administrador.

Confirgurar AUTH_USER_MODEL

Aunque tengamos nuestro modelo Pipol, cuando usemos el comando python manage.py createsuperuser se seguirá creando un modelo User, porque hasta este moemnto, Django no sabe que vamos a usar otro modelo para manejar nuestras cuentas.

Para definir este comportamiento debemos actualizar el valor de settings.AUTH_USER_MODEL, agregando esta línea en el archivo de configuración, que en nuestro caso está en cmi/settings/base.py.

AUTH_USER_MODEL = 'nucleo.Pipol'

Notas


  1. DRY es Don’t Repeat Yourself algo así como No seas repetitivo

Javier Sanchez Toledano

Soy programador en Django+Python y WordPress. Auditor líder certificado en la norma ISO 9001:2008. Fotógrafo aficionado.
Redes Sociales:

Tlaxcala, México

Comentarios