Modelos abstractos en Django



@eduardo_gpg

Número de visitas 1623

Tiempo de lectura 3 min

13 Noviembre 2021

En una entrega anterior hablamos acerca de relaciones polimórficas con Django, donde definimos una relación entre un curso y múltiples items, donde un item puede ser de tipo vídeo o de tipo artículo.

Si aun no has leído dicho post, te comparto el link para que lo hagas. No te arrepentirás de ello. 🐍

Pues bien, para ese ejemplo trabajamos tanto con el modelo Article como con el Modelo Video. Los cuales quedaron de la siguiente manera:

Video

class Video(models.Model):
    title = models.CharField(max_length=50)
    items = GenericRelation(Item)

    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

    @property
    def item(self):
        if self.items:
            return self.items.first()

        return None

    @property
    def course(self):
        if self.item:
            return self.item.course

        return None

Article

class Article(models.Model):
    title = models.CharField(max_length=50)
    items = GenericRelation(Item)

    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

    @property
    def item(self):
        if self.items:
            return self.items.first()

        return None

    @property
    def course(self):
        if self.item:
            return self.item.course

        return None

Modelos que, como podemos observar, son prácticamente lo mismo, comparten los mismos atributos y los mismos métodos, vaya solo cambien en el nombre de la case. Esto por supuesto esta mal, ya que tenemos código duplicado. Y el código duplicado en nuestros proyectos solo es sinonimo que podemos implementar un refactor y hacer mejor aun las cosas.

Es por ello que ahora me gustaría habláramos acerca de modelos abstractos en Django, modelos que nos permitirán a su vez crear múltiples modelos a partir de una base. 🐜

Si te interesa el desarrollo Python en Web este tutorial sin duda te será de interes.

Bien, sin más dilación, pongamos manos a la obra.

Modelos abstractos 🕵️‍♀️

En Django existe el termino de Abstract model, que no más que un modelo donde definiremos, tanto atributos como métodos comunes para nuestra aplicación. Lo interesante de estos modelos es que no crearán tablas en nuestra base de datos, lo cual nos permitirá usarlos como base para otros modelos.

En mi caso, como pudimos observar, tanto mi clase Video como mi clase Article comparten mucha de su estructura, por lo tanto lo mejor que podemos hacer es implementar un modelo Abstracto. Para mi modelo abstracto quedaría de la siguiente manera.

from django.db import models

class AbstractItem(models.Model):
    title = models.CharField(max_length=50)
    items = GenericRelation(Item)

    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

    class Meta:
        abstract = True

    @property
    def item(self):
        if self.items:
            return self.items.first()

        return None

    @property
    def course(self):
        if self.item:
            return self.item.course

        return None

Dentro de la clase colocaremos todos los atributos y métodos duplicados. 🤯

En mi caso la clase tiene por nombre ItemAbstract. Si bien no es necesario tener el sufijo Abstract, en lo personal me ha servido muchísimo esta convención en mis proyecto, ya que se identifica de forma muy rápida todos aquellos modelos que son abstractos de los que no.

En primera instancia la clase se ve como un clásico modelo de Django, sin embargo hay una ligera diferencia, hemos definido el atributo abstract _ como True para la clase _Meta. Esto le indica a Django que el modelo será abstracto, y no podrá crear una tabla en la base de datos.

Una vez con la clase abstracta lo siguiente que debemos hacer es heredar de ella. Algo bastante sencillo.

class Article(AbstractItem):
    pass
class Video(AbstractItem):
    pass

Y listo, como podemos observar ahora nuestro código se ha reducido drásticamente.

Por supuesto, si quisiéramos sobre escribir alguno de los método de la clase abstracta y modifica su comportamiento podemos hacerlo. De igual forma podemos añadir nuevos atributos a las clases hijas. 🧐

class Video(AbstractItem):
    duration = models.IntegerField(default=0, null=False, blank=False)

    def __str__(self):
        return f'Video #{self.title}'

    def minutes(self):
        return duration / 60

Y listo, de esta forma tan sencilla es como podemos definir modelos Abstractos en Django, modelos los cuales no crearán tablas en la base de datos y permitirán abstraer tanto atributos como métodos en nuestra aplicación, siendo capaces de poder utilizarlos estos modelos para poder crear otros modelos a partir de ellos. Super útil cuando tenemos código duplicado y queremos que nuestros proyectos sean mucho más flexibles, robustos y sobre todo fácil de mantener. 🍻


¿El contenido te resulto de ayuda?

Para poder dejar tu opinión es necesario ser un usuario autenticado. Login

Juan Carlos Ortega

Excelente Articulo, a usar mas clases abstractas.

Más Tips y Ejercicios 🐍

Adquiere una subscripción PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 🔓
Nuevo límite: Incrementa tu límite de ejercicios por semana. 🚀
Contenido único: Recibe semanalmente recursos exclusivos de Python (Videos, Artículos y Capitulos del libro PyWombat, comienza como desarrollador Python. 🐍