Django项目部署到Heroku设置DEBUG=False后图片无法显示
问题成因
Django框架默认逻辑为:DEBUG=True 开发模式下,内置开发服务器会自动响应/static/、/media/路径下的静态资源、媒体文件请求;切换为DEBUG=False生产模式后,Django默认这类资源应由独立Web服务或存储服务托管,不再自动处理对应路由,直接返回404。
同时Heroku平台的文件系统为临时读写层,每次dyno重启、重新部署时,本地写入的所有文件都会被清空,本身就不适合存放用户上传的媒体文件。
修复方案
静态资源(static)修复
你现有配置已经完成了基础的静态路径设置,只需补充生产环境静态文件托管配置即可:
- 安装Heroku官方推荐的静态文件托管依赖whitenoise:
pip install whitenoise - 修改
settings.py中的中间件配置,将'whitenoise.middleware.WhiteNoiseMiddleware'放在安全中间件之后、其余所有中间件之前:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # 新增这行 'django.contrib.sessions.middleware.SessionMiddleware', # 其余原有中间件保持不变 ... ]
- 可选添加静态文件压缩、缓存配置,在
settings.py末尾追加:
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
- 确认Heroku环境变量中没有设置
DISABLE_COLLECTSTATIC,部署时平台会自动执行python manage.py collectstatic --noinput将所有静态文件收集到STATIC_ROOT目录,由whitenoise负责响应请求。
完成以上配置后,项目自带的静态图片、CSS、JS等资源即可正常加载。
媒体文件(media)修复
生产环境不建议让Django直接托管媒体文件,也不能将用户上传的文件存在Heroku本地存储,否则dyno重启后文件会全部丢失:
- 正式生产环境方案:接入S3兼容的对象存储服务(如AWS S3、Cloudflare R2等)托管媒体文件
- 安装依赖:
pip install django-storages boto3 - 在
INSTALLED_APPS中添加'storages' - 在
settings.py中添加存储配置,所有密钥、桶名等敏感信息通过Heroku环境变量读取,不要硬编码在代码中:
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY') AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME') AWS_S3_ENDPOINT_URL = os.getenv('AWS_S3_ENDPOINT_URL') # 非AWS S3服务填写对应兼容接口地址 AWS_S3_CUSTOM_DOMAIN = os.getenv('AWS_S3_CUSTOM_DOMAIN') AWS_DEFAULT_ACL = 'public-read' DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/' - 安装依赖:
- 临时测试方案(仅用于本地/临时部署调试,禁止生产使用):
修改项目根路由文件urls.py,追加媒体文件路由规则,强制Django在生产模式下响应本地媒体文件请求:
注意:该方案下所有上传到Heroku本地的媒体文件,会在下次部署、dyno休眠重启后被永久清除,仅可临时调试使用。from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 原有路由配置保持不变 ... ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
内容的提问来源于stack exchange,提问作者Rafael Henrique
相关产品推荐
相关产品推荐

