"""生产环境配置:PostgreSQL + 严格安全 + Granian。""" import os from django.core.exceptions import ImproperlyConfigured from .base import * # noqa from .base import env DEBUG = False _configured_hosts = os.environ.get("DJANGO_ALLOWED_HOSTS", "").strip() if not _configured_hosts: raise ImproperlyConfigured( "生产环境必须显式设置 DJANGO_ALLOWED_HOSTS(逗号分隔的域名列表)," "不允许默认接受任意 Host 头" ) ALLOWED_HOSTS = [h.strip() for h in _configured_hosts.split(",") if h.strip()] if not ALLOWED_HOSTS: raise ImproperlyConfigured("DJANGO_ALLOWED_HOSTS 解析为空,请填入实际域名") if "*" in ALLOWED_HOSTS: # base 的 read_env 会把 backend/.env(dev 用,含 DJANGO_ALLOWED_HOSTS=*) # 写进 os.environ;生产若不显式覆盖就会静默接受任意 Host。 # 通配符在生产无意义,直接拒绝,强制部署者显式声明域名。 raise ImproperlyConfigured( "生产环境不允许 DJANGO_ALLOWED_HOSTS 含通配符 '*'(可能继承了 dev 的 .env)," "请显式设置真实域名,如 DJANGO_ALLOWED_HOSTS=erp.example.com" ) # PostgreSQL(用 DATABASE_URL 环境变量) DATABASES = { "default": env.db( "DATABASE_URL", default="postgres://dealerhub:dealerhub@pg-main:5432/dealerhub", ) } # 异步连接池 DATABASES["default"]["OPTIONS"] = { "pool": {"min_size": 2, "max_size": 10, "timeout": 10}, } # Redis CACHES = { "default": { "BACKEND": env( "CACHE_BACKEND", default="django.core.cache.backends.locmem.LocMemCache", ), "LOCATION": env("CACHE_LOCATION", default="dealerhub-cache"), } } # 安全 SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 60 * 60 * 24 * 30 # 30 天 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_REFERRER_POLICY = "same-origin" X_FRAME_OPTIONS = "DENY" # 生产不打印 SQL(prod 不继承 dev 的配置,避免 KeyError) # 注意:必须用直接赋值覆盖 base.py 已定义的 dealerhub logger; # setdefault 对已存在的 key 不生效,会导致生产仍是 DEBUG。 LOGGING.setdefault("loggers", {}) LOGGING["loggers"]["dealerhub"] = { "handlers": ["console"], "level": "INFO", "propagate": False, } LOGGING["loggers"]["django"] = { "handlers": ["console"], "level": "INFO", "propagate": False, } LOGGING["loggers"]["django.db.backends"] = { "handlers": ["console"], "level": "WARNING", "propagate": False, }