CAPÍTULO 1 · Un equipo, una base común
Dejar de preparar una versión distinta para cada destino
Mientras SensorHub solo corre en el PC, resulta cómodo tener la configuración junta. Pero basta pensar en publicarlo para que aparezca una lista de diferencias: depuración, hosts, secretos y conexiones. Si resolverlas significa editar settings.py antes de cada entrega, dependemos de recordar todos los cambios y de deshacerlos correctamente al volver a desarrollar.
Convertimos ese archivo en un paquete con base.py, development.py y production.py. La base reúne lo compartido; cada entorno importa esa base y establece sus diferencias. No estamos construyendo dos aplicaciones. Estamos permitiendo que el mismo proyecto se ejecute bajo condiciones distintas, seleccionadas mediante DJANGO_SETTINGS_MODULE.
Django no adivina dónde está instalado. Dejamos explícita la selección al arrancar y aprendemos a comprobarla. Con esa separación ya no necesitamos cambiar el código de una vista para pasar del PC al servidor. Sin embargo, todavía queda una pregunta: si cada entorno tiene valores diferentes, ¿dónde guardaremos esos valores sin dejarlos escritos en el repositorio?
Leer esta parte dentro del relato completo →DEL RELATO A LA PRÁCTICA
Vamos a desarrollar esta decisión con su mapa, explicación, código y ejercicio.
MIRA · CONECTA · COMPRENDE
Un proyecto, tres configuraciones
Las flechas muestran responsabilidades relacionadas; no representan un orden obligatorio de ejecución.
Selecciona una pieza para destacar su responsabilidad.
Leer la explicación del mapa
- Base. Comparte ajustes comunes
- DEV. Facilita desarrollo local
- TEST. Controla pruebas aisladas
- PROD. Exige secretos y hosts
01 / EL PROBLEMA
¿Para qué sirve?
DEBUG, credenciales y hosts tienen consecuencias distintas en local y en servidor. Separar entornos convierte esas diferencias en configuración explícita.
02 / COMPRENDER
El concepto, explicado
El archivo generado por startproject se llama settings.py, no setup.py. Convertimos config/settings.py en el paquete config/settings/ con __init__.py, trasladamos lo compartido a base.py y ajustamos BASE_DIR. El módulo seleccionado importa la base; Django no detecta automáticamente si está en el PC o en Azure.
base.py reúne rutas, apps, middleware, templates y opciones compartidas. development.py importa esa base y habilita facilidades locales. production.py importa la misma base y exige secretos y hosts explícitos. Son módulos Python, no tres archivos que Django combine automáticamente.
DJANGO_SETTINGS_MODULE selecciona development o production. El módulo elegido importa base y puede sobrescribir variables. Evita cambiar a mano manage.py, wsgi.py y asgi.py en cada publicación: usa valores predeterminados con setdefault y una variable de entorno explícita en Azure.
Con config/settings/base.py, BASE_DIR=Path(__file__).resolve().parents[2] apunta a la raíz del proyecto. Un nombre de carpeta envolvente no forma parte del módulo importable salvo que realmente sea un paquete en sys.path.
No pongas DEBUG=True en la base compartida. Déjalo False como punto de partida y True solo en development. La selección del entorno debe poder verificarse sin mostrar secretos.
Responsabilidad de cada archivo
| Archivo | Qué contiene | Qué evita |
|---|---|---|
| base.py | Apps, middleware, templates, rutas y valores comunes | Credenciales y DEBUG local compartidos |
| development.py | Carga .env, DEBUG=True y hosts locales | Usar PROD por accidente |
| production.py | SECRET_KEY requerida, hosts y ajustes HTTPS | Valores inseguros por defecto |
| manage.py / wsgi.py / asgi.py | Selección del módulo y entrada al framework | Editar rutas para cada publicación |
| base.html | Layout y bloques de presentación | Confundir templates con settings |
03 / CONSTRUIR
Implementación paso a paso
- Crea config/settings/__init__.py y mueve configuración común a base.py.
- Define development.py y production.py importando base.
- Carga .env solo en el recorrido local antes de leer valores.
- Define DJANGO_SETTINGS_MODULE en el lanzador o en Azure.
- Comprueba settings.DEBUG y settings.SETTINGS_MODULE con la shell.
04 / APLICAR
Ejemplo en SensorHub
# config/settings/base.py: fragmento común
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parents[2]
DEBUG = False
ROOT_URLCONF = "config.urls"
# config/settings/development.py: archivo independiente
from .base import *
DEBUG = True
ALLOWED_HOSTS = ["localhost", "127.0.0.1"]
# config/settings/production.py: archivo independiente
from .base import *
import os
DEBUG = False
SECRET_KEY = os.environ["SECRET_KEY"]
ALLOWED_HOSTS = [h.strip() for h in os.environ["ALLOWED_HOSTS"].split(",") if h.strip()]
# En manage.py, antes de execute_from_command_line:
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.development")
# En wsgi.py/asgi.py, antes de crear application:
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
# PowerShell local:
# $env:DJANGO_SETTINGS_MODULE = "config.settings.development"
# python manage.py checkCómo leer el ejemplo
- Los fragmentos pertenecen a archivos distintos; no los pegues juntos.
- setdefault respeta una variable ya definida. Producción falla al faltar un secreto obligatorio.
- El tema siguiente completa la carga .env; apps y middleware se explican por separado.
Error habitual
Un import de base después de definir DEBUG=True puede sobrescribir el valor. El orden importa.
05 / PRACTICAR
Tu turno
Añade un timeout configurable que rechace cero y números negativos.
Ver solución orientativa
Convierte el valor a float, valida que sea finito y mayor que cero; si falla, lanza ImproperlyConfigured indicando el nombre de la variable.
06 / VERIFICAR
Cómo sabes que funciona
- Producción arranca con DEBUG=False.
- Una variable requerida ausente produce un error claro.
Para profundizar
Documentación oficial para comprobar configuración, permisos y condiciones vigentes. Revisión del tema: 11 de octubre de 2026.
CONTINUAR LA EXPERIENCIA
El siguiente paso del recorrido:
Variables locales: .env y configuración tipada →Continuar en modo relato