Django es sin duda uno de los Framework web más populares en la actualidad. Grandes empresas como Instagram, Spotify, Bitbucket, Dropbox, entre otras, muchas, muchas más, respaldan a este gran Proyecto.
Hay desarrolladores que simplemente lo adoran y otros que no tanto. 😃 Desde mi punto de vista el Framework es simplemente genial, y hay muchas cosas que me gustan de él, como lo puede ser el administrador de modelos, el motor de templates, la facilidad con la cual podemos crear e implementar pruebas unitarias, entre otras cosas más
Sin embargo también hay cosas que no me terminan de convencer. Cosas/detalles los cuales frameworks del mismo estilo, e inclusive, con menos tiempo en el mercado, lo hacen de una mejor manera.
Es por ello que en esta ocasión me gustaría compartir con todos ustedes 5 cosas las cuales no me gustan de Django, Esto es, por supuesto, una simple opinión personal. Tú tienes toda libertad de no concordar conmigo y tener otro punto de vista. Si es así, me gustaría que debatiremos en la sección de comentarios.
Bien, sin más dilación comencemos con este listado.
ORM
El ORM de Django, es quizás, el feature que menos me agrande del Framework. Si bien es cierto que con él seremos capaces de interactuar con nuestra base de datos sin la necesidad de conocer el lenguaje de consultas SQL, creo que el hecho de utilizar el atributo objects y no la misma clase model para acceder a los datos, hace que se pierda un poco el encanto sobre el ORM.
Por ejemplo, en otros Frameworks web, como lo puede ser Ruby on Rails, una búsqueda simple pudiera quedar de la siguiente manera:
User.where('email is ?', nil).limit(10)
Utilizamos el modelos User, el cual representa a la tabla users, y mediante el método where realizamos la busqueda, limitando la cantidad de resultados a 10. Una sentencia sin duda muy fácil de leer. y Ahora ¿Qué pasa con Django?
La misma consulta quedaría de la siguiente forma:
User.objects.filter(email___isnull=True)[:10]
En este caso para acceder al modelo y obtener la información deseanda, tendremos que utilizar el objeto objects, y a traves de él crear la consulta.
Esto funciona, de eso no hay duda alguna, el problema nace cuando comenzamos a complicar las cosas y queremos definir nuestros propios métodos. Siguiendo la comparación con Ruby on Rails, si queremos definir nuevos métodos sobre nuestros modelos, en rails lo podemos hacer sin ningún problema, creando métodos de clases.
class Video < ActiveRecord::Base
scope :visble,->{ where(visble: true) }
def self.by_gt_duration(duration)
where('duration > ?', duration).visble
end
end
En este caso creo dos nuevos métodos (visible y by gt duration ). Los cuales fácilmente podemos utilizar.
User.visible
User.by_gt_duration 180
Con Django sucede algo curioso. Sin bien es cierto podemos definir métodos dentro de nuestros modelos (Métodos de clase), lo correcto, según la documentación oficial, es apoyarnos de la clase Manager, y es dentro de esta clase donde debemos definir nuestros nuevos métodos, para de esta forma, realizar las peticiones a través del atributo objects.
from django.db import models
class VideoManager(models.Manager):
def get_by_duration(self, duration=0):
return self.filter(duration__gte=duration).filter(visible=True)
class Video(models.Model):
title = models.CharField(max_length=50)
duration = models.IntegerField(default=0)
visible = models.BooleanField(default=False)
objects = VideoManager()
Video.objects.get_by_duration(180)
Esto no solo complica los modelos, agregando un nuevo nivel de abstracción, si no que abre la puerta a otros problemas, como lo puede ser la legibidlidad del código, haciendolo dificil de leer y sobre todo mantener. Y en casos queramos ser aun más flexibles, por ejemplo, reutilizar ciertas condiciones y/o atributos, tendremos que apoyarnos de una tercera clase, la clase QuerySet, agregando así un tercer nivel de abstracción.
from django.db import models
class VideoQuery(models.QuerySet):
def visible(self):
return self.filter(visible=True)
def duration_gte(self, duration):
return self.filter(duration__gte=duration)
class VideoManager(models.Manager):
def get_queryset(self):
return VideoQuery(self.model, using=self._db)
def get_by_duration(self, duration=0):
return self.get_queryset().visible().duration_gte(duration)
class Video(models.Model):
title = models.CharField(max_length=50)
duration = models.IntegerField(default=0)
visible = models.BooleanField(default=False)
objects = VideoManager()
>>> Video.objects.get_by_duration(10)
Aquí la gran pregunta es ¿Por qué?
Con todo esto uno pudiera pensar que, al estilo de Django, las consultas y métodos estan mucho mejor organizados, y hasta cierto punto es verdad. El problema que veo, es que es posible tener el código muy bien organizado sin tener que pasar por tantos niveles de abstracción, tal y como Eloquent, el ORM de Rails, nos lo demuestra, o, no vayamos tan lejos, hay frameworks de Python como Peewee o SQLAlchemy que sinceramente no se complican tanto la vida.
Archivos URLs
Algo que me gusta mucho de Django son sus aplicaciones. Se entiende que cada aplicación será un módulo independiente de otros, teniendo así un bajo nivel de cohesión . Cada aplicación tendrá sus propios recursos para funcionar correctamente, hablamos de modelos, templates, vistas, urls, esperen... las urls no forman parte esencial de una aplicación.
Cuando creamos una aplicación en Django el archivos urls.py simplemente no se crea de forma automática; seremos nosotros, los desarrolladores, quienes debemos hacer esto de forma manual. Es un proceso simple, es verdad, nuevo archivo, urls.py, importamos un par de cosas y listo. Pero de todo esto, algo que no me queda del todo claro es ¿por qué el archivo no se crea de forma automática? siendo que, más del 90% de las ocasiones nuestras aplicación necesitarán utilizar urls. Es más, me atrevo a decir que el archivo urls es mucho más utilizado que los archivos test y admin .py.
Quizás esto en algún futuro se agregue al framework, tal y como lo han hecho muchas cosas más. Si recordamos las migraciones en Django, hasta hace un par de versiones, no eran nativas.
Archivo de configuración
El archivo settings.py es otro archivo que me causa un poco de conflictos. En este archivo colocaremos todas las configuraciones necesarias para nuestro proyecto. Y creo que ese es mi problema, que todas las configuraciones deban encontrarse en un mismo archivo. Definir la base de datos, templates, rutas, logs, configuraciones de correos, trabajos en segundo plano y todo lo que el proyecto necesite, deberá encontrarse en el archivo settings.py
Para proyectos pequeños no debería haber muchos problemas, pero si hablamos de un proyectos con docenas de aplicaciones, módulos externos y cientos de funcionalidades, el archivo podría volverse simplemente un caos. Es cierto, podemos crear otros archivos y simplemente importar lo que necesitemos, de esta forma podemos separar configuraciones para un entorno diferentes, rero, de nuevo, ¿por qué complicarnos tanto? ¿Por qué no crear un módulo config y allí colocar todos los archivos de configuraciones?
Entiendo que el Framework no es convesión sobre configuración, pero creo que ciertas cosas pudieran separarse desde un principio, desde la creación del proyecto mismo. Mi humilde opinión.
Ambientes
Otro problema que creo existe, y va muy relacionado con el archivo settings.py, es el manejo de los ambientes de trabajo. Por lo general para cualquier proyecto deberíamos tener, por lo menos, 3 ambientes de trabajo, me refiero a desarrollo, testing y producción.
El problema con Django es cómo separar cada uno de los ambiente. Por ejemplo, el Framework por si solo, nos ofrece la posibilidad de realizar pruebas unitarias, algo bastante cool la verdad, pero, ¿Quiere que ejecute las pruebas unitarias con la misma base de datos que utilizo en desarrollo y/o producción? no lo creo.
Es cierto, Django nos ofrece la bandera DEBUG que nos permite conocer si estamos en un entorno de desarrollo o producción, sin embargo ¿realmente queremos condicionar todo nuestro código?
Hay aplicaciones y formas las cuales podemos separar los entornos de forma profesional, pero caigo en lo mismo, esto es algo necesario en todos los proyectos, y el hecho que le dediquemos un par de minutos en crear y configurar los entornos no le veo mucho sentido.
Convención sobre configuración
Y por último, o sí!, convención sobre configuración. El hecho que Django no utilice este paradigma para gestionar el proyecto es algo que no me termina de gustar.
Y se que por la misma naturaleza del Framework y del lenguaje mismo (Python) implementar este paradigma no sería posible. Aunque realmente me gustaría que si mi vista tiene por nombre admin y se encuentra en la aplicación users, de forma automática se renderize el archivo admin.html del folder users, pero, esto no es así.
Las vistas basadas en clases intentan solucionar este problema, pero admitamoslo, no es cien por ciento confiable y no se siente orgánico.
Mi principal problema con esto es que a veces, nosotros como desarrolladores, al no seguir estándares de codificación, podemos llegar a tener como resultado código espagueti, claro, esto no es para nada culpa del Framework, pero si creo que implementar este tipo de paradigmas ayudan mucho a los desarrolladores a mejorar de forma profesional, aprendiendo así buenas practicas de desarrollo.
Bien este sería mi pequeño listado de cosas que no me terminan de gustar de Django. Como sabemos nada es perfecto y cada uno ve las cosas de forma diferente. Aunque existan cosas que en lo personal no me gusten del Framework, no por ello lo dejaré de usar, y mucho menos lo dejaré de recomendar, ya que, como mencione anteriormente, Django es una herramienta de desarrollo asombrosa, con la cual sin duda podremos construir proyectos en muy poco tiempo y con poco esfuerzo. 🤠🐍
Y bien ¿Estas de acuerdo con mi listado? ¿Qué otra cosa no te gusta de Django? Dejanoslo saber en la sección de comentarios.