Django: 4 buenas prácticas para empezar a programar.

Muchos desarrolladores cuando comenzamos a aprender un lenguaje o una herramienta acarreamos malas prácticas a la hora de programar. Ésto se debe porque se desconoce el paso correcto al momento de escribir nuestras aplicaciones. A continuación les dejaré algunos tips que deben de tener a la hora de desarrollar sus apps en Django.

Tabla de contenido

  1. Incluir nuestros módulos en una carpeta
  2. Organiza tus aplicaciones en el archivo settings.py
  3. Usa correctamente related_name y related_query_name
  4. No uses OneToOneField

Incluir nuestros módulos en una carpeta

Agrupar las carpetas de nuestros módulos es un plus para organizar nuestro proyecto. Por ejemplo, si comenzamos a desarrollar un sistema de inventario tendríamos cada módulo separado con sus modelos y vistas respectivamente.

  • Login
  • Catálogos
  • Inventario
  • Apis

Agregando esos modulos a nuestra app, les pongo un antes y después de como debe quedar nuestro resultado del árbol de directorio de nuestro proyecto.

     ANTES                                     DESPUÉS

-appdemo                                  -appdemo
    __init__.py                               __init__.py
    settings.py                               settings.py
    urls.py                                   urls.py
    wsgi.py                                   wsgi.py
                                          -apps
-apis                                        -apis           # módulo
    models.py                                     models.py
    urls.py                                       urls.py
    views.py                                      views.py
-catalogos                                   -catalogos      # módulo
    models.py                                     models.py
    urls.py                                       urls.py
    views.py                                      views.py
-inventario                                  -inventario     # módulo
    models.py                                     models.py
    urls.py                                       urls.py
    views.py                                      views.py
-login                                       -login          # módulo
    models.py                                     models.py
    urls.py                                       urls.py
    views.py                                      views.py
-db.sqlite3                                  -db.sqlite3
-manage.py                                   -manage.py

Vamos con un poco de ajustes en el archivo urls.py.

# urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls), #rutas del admin de django
    
    # Aqui nuestras rutas
    path('login/', include('apps.login.urls')),
    path('catalogos/', include('apps.catalogos.urls')),
    path('inventario/', include('apps.inventario.urls')),
    path('apis/', include('apps.apis.urls')),
]

Ahora modifiquemos la variable INSTALLED_APPS en el archivo settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    # Nuestros módulos
    'apps.login',
    'apps.inventario',
    'apps.catalogos',
    'apps.apis',
]

Organiza tus aplicaciones en el archivo settings.py

Una vez separada tus aplicaciones agrupadas en una sola carpeta, también podremos darle otro uso a la variable INSTALLED_APPS. Lo que muchos no saben es que podemos adaptarla a nuestro gusto. Así que la dividiré de 3 formas.

DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize',
]

APPS_DE_TERCEROS = [
    'reversion',
    'corsheaders',
    'password_reset',
    'rest_framework',
    'betterforms',
]

MIS_APPS = [
    'apps.login',
    'apps.inventario',
    'apps.catalogos',
    'apps.apis',
]

INSTALLED_APPS = DJANGO_APPS + APPS_DE_TERCEROS + MIS_APPS

Como ven uso 3 variables y a lo último concatenamos todo en INSTALLED_APPS.

La variable INSTALLED_APPS no puede ser cambiada o renombrada puesto que es leída por Django así que sólo a dicha variable se le puede concatenar la lista de aplicaciones a como se describe en el fragmento de código.

Ésto se vuelve más útil cuando tenemos el settings.py en dos archivos, uno para producción y otro para desarrollo. Las apps para desarrollo pueden ser otras, como por ejemplo, la herramienta django debug toolbar, que no tendría caso que esté en la configuración de nuestro servidor de producción.


Es una buena práctica usar las relaciones inversas en nuestros modelos y django proporciona un fácil acceso a modelos que, aunque en un modelo en especifico no este la relación lo podemos hacer inverso sin problemas. No se preocupen les daré el siguiente ejemplo.

class Persona(models.Model):
    nombre = models.CharField(max_length=50)
    apellido = models.CharField(max_length=50)


class Empleado(models.Model):
    CATEGORIAS = (
        (0, 'Secretario'),
        (1, 'Tesorero'),
        (2, 'Jefe')
    )
    categoria = models.CharField(choices=CATEGORIAS, max_length=2)
    salario = models.DecimalField(max_digits=10, decimal_places=2)
    persona = models.ForeignKey(Persona,
        on_delete=models.CASCADE,
        related_name='empleados',
        related_query_name='empleado')

Lo normal del orm de Django es que podamos acceder a persona desde empleado:

# Obteniendo sólo el primer empleado
persona = Persona.objects.first()
persona.empleados.values('salario',)

Ese filtro lo podemos hacer porque empleado tiene un campo con nombre persona. Ahora hagámos la prueba accediendo a Empleado desde Persona.

# Haciendo una búsqueda con filter
personas = Persona.objects.filter(empleado__salario=1000)

Como hemos notado, en el modelo Persona no tenemos ningun campo relacionado que nos deje acceder a empleado, pero por medio del related_name y related_query_name tenemos la facilidad de acceder de Persona -> Empleado sin problemas.

Si no quisieramos que nuestros modelos tengan relaciones inversas entonces le agregamos un signo '+' a related_name.


persona = models.ForeignKey(Persona,
        on_delete=models.CASCADE,
        related_name='+')


No uses OneToOneField a menos que sepas cuándo usarlo

Así es. Aunque éste tipo de campo existe en django, es mejor evitar su uso. Lo difícil es cuando por algún momento queremos cambiarlo por alguno como ForeignKey. Recuerda que, los requerimientos de usuario cambian constantemente y es impredecible saber si ya no lo cambiaremos -a menos- que sí estemos seguros que ese requerimiento no cambiará por nada en el mundo.


Espero que les sea de bendición y nos leemos hasta la próxima!