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, localhost
Lenguaje del código: PHP (php)
En tu archivo .gitignore
agrega lo siguiente:
.env
Lenguaje del código: 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-decouple
Lenguaje del código: Bash (bash)
En tu settings.py
importa la biblioteca:
from decouple import config
Lenguaje del código: JavaScript (javascript)
Y para acceder a un valor definido en el archivo .env
hacemos lo siguiente:
SECRET_KEY = config("SECRET_KEY")
Lenguaje del código: 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 booleanoTrue
oFalse
.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())
Lenguaje del código: 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)
Lenguaje del código: 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
}
}
Lenguaje del código: 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-host3
Lenguaje del código: 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.
3 respuestas
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=»»),
}
}
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.
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???