在Digital Ocean部署Django/Wagtail时,导航为何会销毁管理员会话?
解决Digital Ocean部署Wagtail/Django时会话频繁丢失的问题
核心问题分析
部署在Digital Ocean App Platform的Wagtail/Django应用,进入管理面板编辑页面时会话被强制销毁,Cookie过期时间被重置为1970年(会话失效标记),django-admin也出现相同问题。结合部署场景,主要排查以下几个方向:
1. 动态生成SECRET_KEY导致会话失效
如果代码里用get_random_secret_key()生成SECRET_KEY,Digital Ocean App Platform每次部署、实例重启或扩缩容时,都会重新生成这个密钥。而Django的会话加密、签名完全依赖固定的SECRET_KEY,密钥变更会直接导致所有现有会话失效,触发重新登录。
解决方法:
- 在Digital Ocean应用的「Settings -> Environment Variables」中添加固定的
SECRET_KEY变量(可本地用get_random_secret_key()生成一次后复制过去); - 修改代码从环境变量读取密钥:
import os SECRET_KEY = os.environ.get("SECRET_KEY")
2. SQLite会话存储的局限性
用SQLite作为数据库(包括会话存储)时,Digital Ocean App Platform的无状态实例特性会引发问题:
- 多实例运行时,每个实例的SQLite文件独立,会话数据无法共享;
- 实例重启或重新部署时,SQLite文件会被重置,之前的会话数据全部丢失。
解决方法:
- 临时测试:切换到本地内存缓存作为会话后端(仅单实例可用),修改
settings.py:SESSION_ENGINE = "django.contrib.sessions.backends.cache" CACHES = { "default": { "BACKEND": "django.core.cache.backends.locmem.LocMemCache", } } - 生产/ staging环境:改用Digital Ocean Managed Redis或PostgreSQL作为会话存储,Redis配置示例:
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": os.environ.get("REDIS_URL"), "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } SESSION_ENGINE = "django.contrib.sessions.backends.cache"
3. Cookie安全配置不符合HTTPS环境要求
Digital Ocean App Platform默认强制HTTPS,如果Django的Cookie配置不正确,浏览器会拒绝保存或发送会话Cookie:
SESSION_COOKIE_SECURE必须设为True,否则浏览器在HTTPS环境下不会保存Cookie;SESSION_COOKIE_SAMESITE建议设为Lax或Strict,避免跨站请求时Cookie被阻断;- 检查
SESSION_COOKIE_DOMAIN是否与应用域名匹配。
修改settings.py示例:
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "Lax" # 自定义域名场景下设置: # SESSION_COOKIE_DOMAIN = "your-app-domain.com"
4. Gunicorn多Worker的会话共享问题
如果Gunicorn配置了多个worker,而会话存储是本地类型(如LocMem、SQLite),不同worker之间无法共享会话数据,当请求路由到不同worker时,会出现会话找不到的情况,触发重新登录。
解决方法:
- 改用共享式会话存储(Redis/数据库),确保所有worker能访问同一会话数据源;
- 临时测试可将worker数设为1(不推荐生产环境),启动命令添加
--workers 1。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

