Cómo configurar variables de entorno en Django

Entrada: Cómo configurar variables de entorno en Django

Recuerda que cada aplicación web que desarrolles, probablemente se va a ejecutar en mas de un entorno (tanto locales, como en producción). Y necesitarás cambiar algunos parámetros para que funcione correctamente. Por ejemplo, cuando estas desarrollando localmente necesitas que los parámetros de base de datos estén vinculados a la base de datos local y que el DEBUG este en True. Pero cuando vas a desplegarlo necesitas cambiar, otra vez, estos parámetros. Cambiar el DEBUG a False y cambiar los valores de la base de datos.

Por ello, necesitamos aislar estos valores, para no estar manoseando a cada rato nuestro código cuando cambiemos de entorno. Además, es recomendable aislar estos valores al momento de iniciar un proyecto, para que el control de versiones no haga seguimiento a estos datos que casi siempre son sensibles. Pero, ¿Cómo separamos estos valores del código? Simple, con la ayuda de las variables de entorno.

Crear variables de entorno

Crea un archivo .env en la raíz de tu proyecto. Ahí agregaremos nuestras variables de entorno, recuerda actualizar los valores con los de tu proyecto:

SECRET_KEY=django-insecure-^prw$_z^2)+x0omx@d%p-toes4-+z+_kl(=$duc@qgi3^@8s*v
DEBUG=True
DB_NAME=tiendaonline
DB_USER=postgres
DB_PASSWORD=post123
DB_HOST=localhost
ALLOWED_HOSTS=127.0.0.1, localhostCode language: PHP (php)

En tu archivo .gitignore agrega lo siguiente:

.envCode language: Bash (bash)

Para que nuestra aplicación Django pueda leer los valores del archivo .env necesitamos la ayuda de una biblioteca. Veamos la mejor opción entre python-decouple y django-environ.

¿Python Decouple o Django Environ?

Si ya tienes un poco de experiencia en la configuración de variables de entorno en Django, lo mas probable es que hayas usado django-environ o python-decouple. Ambas bibliotecas te permiten acceder a parámetros desde un archivo .env. El problema surge cuando vas a desplegar tu aplicación en algún PaaS como Heroku que ejecuta los archivos de tu repositorio Git, y no te permite crear archivos nuevos. En este caso, el archivo .env no nos sirve, simplemente porque no podemos crearlo. Alternativamente habrá que definir las variables de entorno en el sistema. La biblioteca django-environ no te permite leer las variables del sistema, solo se limita a archivos. Por este motivo, si queremos adaptar nuestro proyecto a la gran mayoría de entornos, la mejor opción es python-decouple, porque leerá el archivo .env y las variables de entorno definidas en el sistema.

Artículo recomendado: 12 sitios webs populares creados con Django

Instalación de Python Decouple

Primero instalemos la biblioteca:

pip install python-decoupleCode language: Bash (bash)

En tu settings.py importa la biblioteca:

from decouple import configCode language: JavaScript (javascript)

Y para acceder a un valor definido en el archivo .env hacemos lo siguiente:

SECRET_KEY = config("SECRET_KEY")Code language: JavaScript (javascript)

Antes de traer las demás variables de entorno aprendamos un poco de la conversión de datos y los valores por defecto.

Conversión de datos

De manera predeterminada decouple trae los valores en formato string, pero un proyecto Django necesita diversos tipos de valores como los siguientes:

  • DEBUG espera un valor booleano True o False.
  • ALLOWED_HOSTS espera una lista de hosts.
  • EMAIL_PORT espera un número entero.

Para ello tenemos el argumento cast:

# De string a booleano
DEBUG = config("DEBUG", cast=bool)

# De string a entero
EMAIL_PORT = config('EMAIL_PORT', cast=int)

# Forma 1: De string a lista
ALLOWED_HOSTS = config(
    'ALLOWED_HOSTS', cast=lambda v: [s.strip() for s in v.split(',')]
)

# Forma 2: De string a lista
from decouple import Csv

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())Code language: Python (python)

Valores por defecto

Puedes agregar valores predeterminados que se usarán en caso de que no existan en el archivo .env con el argumento default:

DEBUG = config('DEBUG', default=True, cast=bool)Code language: Python (python)

Implementación Final

Ahora sí, veamos como quedaría nuestro settings.py con todo lo aprendido:

from decouple import config, Csv

SECRET_KEY = config("SECRET_KEY")

DEBUG = config("DEBUG", default=False, cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())

DATABASES = {
    "default":
        {
            "ENGINE": "django.db.backends.postgresql_psycopg2",
            "NAME": config("DB_NAME"),
            "USER": config("DB_USER"),
            "PASSWORD": config("DB_PASSWORD"),
            "HOST": config("DB_HOST"),
            "PORT": 5432
        }
}Code language: JavaScript (javascript)

Si ejecutas tu proyecto en tu entorno local, funcionará normal, y si lo ejecutas en un entorno de producción tienes la opción de crear un archivo .env con los nuevos valores o asignar directamente las variables en el sistema. Gracias a python-decouple tendrás ambas opciones a la mano.

Recomendaciones

Como no estamos agregando el archivo .env al repositorio de Git, es recomendable crear un archivo .env.example en la raíz de tu proyecto para que otras personas se guíen y sepan que variables de entorno se deben asignar al proyecto. Puedes añadir a tu archivo algo parecido a esto:

SECRET_KEY=tu-clave-secreta
DEBUG=False
DB_NAME=tu-nombre-de-db
DB_USER=tu-db-user
DB_PASSWORD=tu-db-password
DB_HOST=tu-db-host
ALLOWED_HOSTS=tu-host1, tu-host2, tu-host3Code language: PHP (php)

Y la última recomendación es que compartas este artículo, y, si tuviste algún problema, déjame un comentario con los detalles para poder apoyarte.

Compartir:
Suscríbete para recibir artículos de desarrollo web

En este boletín envío correos relacionados al área del diseño y desarrollo web. Escribo sobre WordPress y AstroJS, a veces un poco de UX/UI.

3 Responses

  1. Amigo ayer mismo estaba yo por mi cuenta pensando la mejor manera de organizar esto de las variables de entorno y mi archivo es casi igual al tuyo al tuyo excepto que yo no puse ALLOWED_HOSTS y puse DB_ENGINE.
    En mi proyecto yo quiero usar en local una DB SQLlite y en despliegue un postgresql, entonces creé 2 archivos de ejemplo para que cada quién cree su .env
    .env.dev
    DEBUG = 1
    SECRET_KEY = “ThisTokenIsNotSoSecretChangeIt”

    .env.prod
    DEBUG = 0
    SECRET_KEY = “ThisTokenIsNotSoSecretChangeIt”
    DB_ENGINE =django.db.backends.postgresql,
    DB_NAME =”database-name”
    DB_USER =”user”
    DB_PASSWORD =”password”
    DB_HOST =”localhost”
    DB_PORT =”5432″,

    En settings.py en las distintas partes puse:
    from decouple import config
    SECRET_KEY = config(‘SECRET_KEY’)
    DEBUG = config(‘DEBUG’, default=False, cast=bool)
    DATABASES = {
    ‘default’: {
    ‘ENGINE’: config(‘DB_ENGINE’, default=”django.db.backends.sqlite3″),
    ‘NAME’: config(‘DB_NAME’, default=BASE_DIR / ‘db.sqlite3’),
    ‘USER’: config(‘DB_USER’, default=””),
    ‘PASSWORD’: config(‘DB_PASSWORD’, default=””),
    ‘HOST’: config(‘DB_HOST’, default=””),
    ‘PORT’: config(‘DB_PORT’, default=””),
    }
    }

  2. Antes usaba un json,
    with open(r”path”) as config_file:
    CONFIG = json.load(config_file)
    y tomaba los valores, me andaba bien, el problema era que el sistema de archivos en prod y en dev eran diferentes, entonces cada vez que havia un deply tenia que estar cambiando eso. Con el .env no tendria ese problema. Pero desde que lo pude, no me toma los archivos estaticos, es raro, porque el .env no tiene nada que ver con eso pero no los encuentra.

  3. Uso python-decouple hace tiempo sin problemas, sin embargo ahora se me presento el siguiente error al querer hacer unos scripts usando variables de entorno y me arroja el siguiente error:

    from decouple import config

    ModuleNotFoundError: No module named ‘decouple’

    Sabes como solucionarlo???

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *

12 Webs famosas que han sido creadas con Django

Como crear Context Processors en Django

Cómo usar Django Signals

Encuéntrame en: