Django + PostgreSQL: conexión segura con .env (dotenv)

Gabriel Gómez Gómez ·

Django + PostgreSQL: conexión segura con .env (dotenv)

  • Conectaremos tu proyecto Django 5.2.x a PostgreSQL usando variables de entorno con python-dotenv. Así evitamos exponer secretos y mantenemos entornos (dev/prod) aislados.

  • 1) Instala dependencias (driver y dotenv). Usa el binario de psycopg para simplificar.

  • terminalBASH
    source .venv/bin/activate   # (Windows: .venv\Scripts\Activate.ps1)
    pip install "psycopg[binary]~=3.2" python-dotenv
    pip freeze > requirements.txt
  • 2) Crea tu base de datos y usuario en PostgreSQL (si aún no existen).

  • psqlSQL
    -- Dentro de psql (o usa PGAdmin)
    CREATE ROLE mi_usuario WITH LOGIN PASSWORD 'mi_password';
    ALTER ROLE mi_usuario SET client_encoding TO 'UTF8';
    ALTER ROLE mi_usuario SET default_transaction_isolation TO 'read committed';
    ALTER ROLE mi_usuario SET timezone TO 'America/Mexico_City';
    CREATE DATABASE mi_db OWNER mi_usuario;
    GRANT ALL PRIVILEGES ON DATABASE mi_db TO mi_usuario;
  • 3) Crea un archivo .env en la raíz del proyecto (junto a manage.py) con las variables para la conexión.

  • terminalBASH
    cat > .env << 'EOF'
    # --- DATABASE ---
    DB_NAME=mi_db
    DB_USER=mi_usuario
    DB_PASSWORD=mi_password
    DB_HOST=localhost
    DB_PORT=5432
    
    # --- DJANGO ---
    DEBUG=True
    SECRET_KEY=pon-una-seed-larga-y-unica
    ALLOWED_HOSTS=127.0.0.1,localhost
    EOF
  • 4) Carga .env en settings. Usa python-dotenv y os.getenv. Asegúrate de importar os.

  • config/settings.pyPYTHON
    # config/settings.py
    import os
    from pathlib import Path
    from dotenv import load_dotenv
    
    BASE_DIR = Path(__file__).resolve().parent.parent
    load_dotenv(BASE_DIR / ".env")
    
    DEBUG = os.getenv("DEBUG", "False").lower() == "true"
    SECRET_KEY = os.getenv("SECRET_KEY", "change-me")
    ALLOWED_HOSTS = [h.strip() for h in os.getenv("ALLOWED_HOSTS", "").split(",") if h.strip()] or ["127.0.0.1", "localhost"]
    
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": os.getenv("DB_NAME"),
            "USER": os.getenv("DB_USER"),
            "PASSWORD": os.getenv("DB_PASSWORD"),
            "HOST": os.getenv("DB_HOST", "localhost"),
            "PORT": os.getenv("DB_PORT", "5432"),
            # Opcional en producción (ej. Railway/Render/AWS RDS):
            # "OPTIONS": {"sslmode": "require"},
        }
    }
  • 5) Verifica que Django detecta la conexión (aplica migraciones base y ejecuta).

  • terminalBASH
    python manage.py check
    yes "" | python manage.py makemigrations  # (no crea nada si no hay modelos nuevos)
    python manage.py migrate
    python manage.py runserver 8000
  • 6) Prueba rápida con un modelo simple para confirmar escritura/lectura.

  • core/models.pyPYTHON
    # core/models.py
    from django.db import models
    
    class Ping(models.Model):
        creado = models.DateTimeField(auto_now_add=True)
    
  • terminalBASH
    python manage.py makemigrations core
    python manage.py migrate
    python manage.py shell -c "from core.models import Ping; Ping.objects.create(); print(Ping.objects.count())"
  • 7) Buenas prácticas para producción.

  • • Nunca subas .env al repositorio (usa .gitignore).
    • Cambia
    DEBUG=False, configura ALLOWED_HOSTS y añade sslmode=require cuando tu proveedor lo pida.
    • Usa un usuario de DB con permisos mínimos (no superuser) y rota credenciales si hay incidentes.
    • Mantén backups automáticos y monitoreo de conexiones.

  • 8) Errores comunes y cómo resolverlos (rápido).

  • psycopg.OperationalError: connection refused: Verifica DB_HOST, DB_PORT y que PostgreSQL esté iniciado.
    password authentication failed: Usuario/clave o pg_hba.conf mal configurados.
    • Migraciones atascadas: revisa
    python manage.py showmigrations y asegura que la base apuntada es la correcta.
    .env no cargado: confirma la ruta en load_dotenv(BASE_DIR / ".env") y que os.getenv devuelve valores.

  • 9) (Opcional) Variables de entorno del sistema/servidor. En contenedores o PaaS, define las keys (DB_NAME, DB_USER, etc.) en el panel y omite el .env, o cópialo vía secretos (no en la imagen).

  • Con esto tu Django queda conectado a PostgreSQL mediante variables de entorno gestionadas por dotenv. ¿Quieres que lo dejemos listo con docker-compose (Django + Postgres + pgAdmin) y volúmenes persistentes?