Ficha del módulo
- ID: django-preparacion-app
- Categoría: django
Preparación de aplicación Django
🎯 Objetivo: preparar una aplicación Django para despliegue y carga a servidor.
Estructura requerida
El proyecto Django debe tener la siguiente estructura. Los tres primeros archivos se crearán en los pasos siguientes.
proyecto/
├── Procfile ← ver paso siguiente
├── runtime.txt ← ver paso siguiente
├── requirements.txt ← ver paso siguiente
│── manage.py
│── proyecto/
│ ├── settings/
│ │ ├── base.py
│ │ ├── development.py
│ │ └── production.py
│ ├── wsgi.py / asgi.py
│ ├── urls.py
└── apps/
Crear archivo Procfile
El archivo Procfile establece cómo se debe ejecutar la aplicación en Dokku. No debe llevar ninguna extensión de archivo. Dentro se pueden definir uno o más servicios y acciones a ejecutar en cada despliegue (release).
web: gunicorn proyecto.wsgi:application --bind 0.0.0.0:$PORT --workers 3 --timeout 60
release: python manage.py migrate --noinput && python manage.py collectstatic --noinput
Breve explicación:
web: Corresponde al proceso principal de gunicorn que sirve la aplicación.release: Define las acciones a ejecutar antes de cada despliegue. En este caso, se ejecutan las migraciones y se recogen los archivos estáticos en el servidor.
Crear archivo runtime.txt
El archivo runtime.txt contiene la versión de Python que se debe utilizar en Dokku para la aplicación. Ajustar versión según sea necesario.
python-3.11.9
Para ver las versiones soportadas, visitar Heroku Python Supported Runtimes.
Crear archivo requirements.txt
El archivo requirements.txt contiene las dependencias de la aplicación.
Para crear el archivo por primera vez, utilizar el siguiente comando:
# dentro del entorno virtual del proyecto
pip freeze > requirements.txt
Luego, editar el archivo para agregar las dependencias de producción.
# para producción
gunicorn==21.2.0
psycopg2-binary==2.9.9
whitenoise==6.6.0
django-environ==0.11.2
dj-database-url==2.1.0
Archivos settings por entorno
El archivo settings.py contiene la configuración base de la aplicación. Este archivo puede ser desglosado en archivos por entorno, como base.py, development.py y production.py.
Por defecto, un proyecto de Django solamente incluye un archivo settings.py.
Para crear los archivos por entorno, crear una carpeta settings dentro del proyecto e incluir los archivos base.py, development.py y production.py con los siguientes contenidos:
settings/base.py
from pathlib import Path
import environ
BASE_DIR = Path(__file__).resolve().parent.parent.parent
env = environ.Env()
SECRET_KEY = env("SECRET_KEY", default="dev-insecure-key")
DEBUG = False
ALLOWED_HOSTS = []
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# apps propias
# "apps.core",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "config.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
}
]
WSGI_APPLICATION = "config.wsgi.application"
LANGUAGE_CODE = "es-cl"
TIME_ZONE = "America/Santiago"
USE_I18N = True
USE_TZ = True
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
settings/development.py
from .base import *
DEBUG = True
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "0.0.0.0"]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
INSTALLED_APPS += [
# "debug_toolbar",
]
MIDDLEWARE += [
# "debug_toolbar.middleware.DebugToolbarMiddleware",
]
INTERNAL_IPS = ["127.0.0.1"]
settings/production.py
from .base import *
import dj_database_url
SECRET_KEY = env("SECRET_KEY")
DEBUG = env.bool("DEBUG", default=False)
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS")
CSRF_TRUSTED_ORIGINS = env.list(
"CSRF_TRUSTED_ORIGINS",
default=[]
)
DATABASES = {
"default": dj_database_url.config(
default=env("DATABASE_URL"),
conn_max_age=600,
ssl_require=env.bool("DB_SSL_REQUIRE", default=False),
)
}
MIDDLEWARE.insert(
1,
"whitenoise.middleware.WhiteNoiseMiddleware"
)
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
SECURE_SSL_REDIRECT = env.bool("SECURE_SSL_REDIRECT", default=True)
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = env.int("SECURE_HSTS_SECONDS", default=31536000)
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool("SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True)
SECURE_HSTS_PRELOAD = env.bool("SECURE_HSTS_PRELOAD", default=True)
X_FRAME_OPTIONS = "DENY"
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_REFERRER_POLICY = "same-origin"
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
Modificar según sea necesario.