website / src /backend /research_api /settings.py
Andrej Janchevski
fix(deploy): harden container runtime and unify research / checkpoint roots
5375c2e
import os
import sys
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
PROJECT_ROOT = BASE_DIR.parent.parent # Website root in dev; ignored in the container
# Research code root. In the deployment image this is /app/research; in dev
# it defaults to <repo>/src/research. Defined early because the sys.path
# additions below depend on it.
RESEARCH_ROOT = Path(os.environ.get("RESEARCH_ROOT", PROJECT_ROOT / "src" / "research"))
# Add research repos to sys.path so their modules can be imported
_COINS_KG_ROOT = str(RESEARCH_ROOT / "COINs-KGGeneration")
_DIGRESS_KG_SRC = str(RESEARCH_ROOT / "COINs-KGGeneration" / "graph_generation" / "src")
_MULTIPROXAN_ROOT = str(RESEARCH_ROOT / "MultiProxAn")
_MULTIPROXAN_SRC = str(RESEARCH_ROOT / "MultiProxAn" / "src")
for _path in (_COINS_KG_ROOT, _DIGRESS_KG_SRC, _MULTIPROXAN_ROOT, _MULTIPROXAN_SRC):
if _path not in sys.path:
sys.path.insert(0, _path)
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "dev-insecure-key-change-in-production")
DEBUG = os.environ.get("DJANGO_DEBUG", "True").lower() in ("true", "1")
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")
INSTALLED_APPS = [
"corsheaders",
"rest_framework",
"django.contrib.staticfiles",
"api",
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "research_api.urls"
WSGI_APPLICATION = "research_api.wsgi.application"
DATABASES = {}
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer"],
"DEFAULT_PARSER_CLASSES": ["rest_framework.parsers.JSONParser"],
"DEFAULT_PAGINATION_CLASS": None,
"DEFAULT_AUTHENTICATION_CLASSES": [],
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.AllowAny"],
"EXCEPTION_HANDLER": "api.exceptions.api_exception_handler",
"UNAUTHENTICATED_USER": None,
}
CORS_ALLOWED_ORIGINS = [
o.strip() for o in os.environ.get(
"CORS_ALLOWED_ORIGINS", "https://bani57-website.hf.space"
).split(",") if o.strip()
]
if DEBUG:
CORS_ALLOW_ALL_ORIGINS = True
# Security headers (active when DEBUG=False). Gated on DEBUG so local dev
# over plain HTTP doesn't get redirected/blocked.
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_REFERRER_POLICY = "same-origin"
X_FRAME_OPTIONS = "DENY"
if not DEBUG:
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = False # HF Spaces terminates TLS upstream; redirect would loop
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = False
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
CSRF_TRUSTED_ORIGINS = [o for o in CORS_ALLOWED_ORIGINS if o.startswith("https://")]
# Checkpoints land here at runtime via huggingface_hub.snapshot_download.
# Defaults to RESEARCH_ROOT (defined above) for dev where weights sit alongside
# the research code; the deployment image overrides to /app/checkpoints.
CHECKPOINTS_ROOT = Path(os.environ.get("CHECKPOINTS_ROOT", RESEARCH_ROOT))
# Research code paths
COINS_DATA_DIR = RESEARCH_ROOT / "COINs-KGGeneration" / "data"
COINS_COMPLETION_DIR = CHECKPOINTS_ROOT / "COINs-KGGeneration" / "graph_completion"
DIGRESS_KG_DIR = CHECKPOINTS_ROOT / "COINs-KGGeneration" / "graph_generation"
MULTIPROXAN_DIR = CHECKPOINTS_ROOT / "MultiProxAn"
# Static files & SPA dist (Vue's npm run build output, copied into the image)
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
SPA_DIST_DIR = Path(os.environ.get("SPA_DIST_DIR", BASE_DIR / "dist"))
WHITENOISE_ROOT = str(SPA_DIST_DIR)
WHITENOISE_INDEX_FILE = "index.html"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# PyTorch device: auto-detect CUDA, allow override via env var
import warnings
warnings.filterwarnings("ignore", message="TypedStorage is deprecated")
import torch as _torch
TORCH_DEVICE = os.environ.get("TORCH_DEVICE", "cuda:0" if _torch.cuda.is_available() else "cpu")