Programación

Proyecto Django en producción: settings

Nekmo

Mayo 22, 2016

Python Django production Django

En este artículo se tratará cómo tener más de un archivo settings en nuestro proyecto Django para tener una configuración para desarrollo, otra para producción...

Esta es la primera parte de una serie de artículos de cómo debemos poner nuestro proyecto Django en producción (o lo que es lo mismo: cómo publicar nuestro trabajo). Se presupone que tenemos ya un proyecto, además de un servidor propio (VPS o dedicado) y conocimientos sobre Unix/Linux.

Tal y como se crea nuestro proyecto Django, no es muy práctico para tener varios archivos de configuración, cosa esencial para tener un settings para trabajar (develop) y otro para ElMundoReal™ (production). Esto es esencial porque hay cosas que cambian de uno a otro, y en las que nos centraremos en el próximo artículo, como:

DEBUG, ALLOWED_HOSTS, DATABASES, LOGGING, SITE_ID, STATIC_ROOT, MEDIA_ROOT, SECRET_KEY...

Así pues, vamos a cambiar nuestra forma de trabajar con el settings casi por completo. Hay quienes antes de dividir su settings, convierten sus configuraciones a JSON, Yaml o a un archivo ini. En mi opinión, esto es una mala idea salvo que estemos haciendo un programa pensado a usuarios finales. Si lo estamos haciendo para nosotros, será siempre mucho más cómodo seguir usando Python, porque podremos seguir haciendo uso de funciones, porque necesitaremos usar gettext, por casos como el de Celery, o por no pasar nuestro tiempo convirtiendo de Python a JSON las configuraciones de todas nuestras dependencias.

Nuestro objetivo será pasar de una estructura como esta:

- proj/
- proj/__init__.py
- proj/settings.py
- proj/urls.py
- manage.py

A esta otra:

- proj/
- proj/__init__.py
- proj/settings/
- proj/settings/__init__.py
- proj/settings/defaults.py
- proj/settings/develop.py
- proj/settings/production.py
- proj/urls.py
- manage.py

¿Y en qué consiste exactamente? Tendremos un archivo principal llamado defaults.py con todo aquello que sea común en todas las configuraciones (aunque podremos sobrescribirlo), y luego crear archivos que extiendan dicha configuración (los develop.py y production.py)

Así pues, en defaults.py pondremos cosas como las INSTALLED_APPS o las MIDDLEWARE_CLASSES, y en los otros archivos las específicas del entorno. Podremos empezar cogiendo todo nuestro archivo settings.py, renombrarlo a defaults.py, e introducirlo dentro de la carpeta settings que crearemos siguiendo la estructura anterior. Recuerda crear un archivo __init__.py dentro de la carpeta.

Ahora, el truco para que esto funcione, será poner al comienzo de develop.py y production.py, una línea con lo siguiente:

# settings/develop.py
# -------------------
from .defaults import *

Con esto estaremos importando todo de defaults.py, haciéndolo disponible en develop.py. Y sí, sé que from module import * no es algo recomendado, pero para el caso nos viene ni que pintado. Resumiendo:

~/projects/my-project/$ cd myproject
~/projects/my-project/myproject/$ mkdir settings
~/projects/my-project/myproject/$ mv settings.py settings/defaults.py
~/projects/my-project/myproject/$ touch settings/__init__.py
~/projects/my-project/myproject/$ echo "from .defaults import *" > settings/develop.py
~/projects/my-project/myproject/$ echo "from .defaults import *" > settings/production.py

Vale, ahora el problema, es que Django no sabe qué settings utilizar. Mejor dicho, sigue pensando que se encuentra en myproject.settings, y ahora estará en myproject.settings.developmyproject.settings.production. Tal y como se encuentra ahora mismo usará el __init__.py de la carpeta settings, y ahí no hay nada. Tenemos que especificar el archivo a utilizar. Para ello, contamos con 2 opciones:

  1. Definir la variable de entorno DJANGO_SETTINGS_MODULE.
  2. Establecer como parámetro en manage.py (o wsgi.py) la opción --settings.

Hay una tercera opción, y es modificar los archivos manage.py y myproject/wsgi.py para obtener dinámicamente la configuración por defecto, pero sólo lo recomiendo si tenemos muchas máquinas. Un ejemplo por cada uno de los anteriores casos son:

  1. DJANGO_SETTINGS_MODULE=nekmocom.settings.develop ./manage.py runserver
  2. ./manage.py runserver --settings=nekmocom.settings.develop

Si usamos un IDE, podremos definir el settings por alguna de las 2 formas anteriores para evitar tener que definirlo siempre. En el caso de PyCharm, tiene la suya propia para Django:

Gracias por leer, ¡y suerte con tu proyecto!