Docker配置FORCE_SCRIPT_NAME后Django staticfiles无法加载CSS
临时解决方案
已解决该问题,推测是FORCE_SCRIPT_NAME、STATIC_URL必须以/结尾的要求,以及django.conf.urls.static的行为三者之间的不良交互导致。
有效配置如下:
urls.py
from django.conf.urls.static import static urlpatterns += static("static", document_root=settings.STATIC_ROOT)
settings.py
FORCE_SCRIPT_NAME = "/the-prefix-i-need/" STATIC_ROOT = "/static/" STATIC_URL = "static/"
注意:
STATIC_URL必须以/结尾(否则runserver会运行失败),但如果static的第一个参数以/开头,它会将FORCE_SCRIPT_NAME纳入要匹配的URL模式,导致无法匹配/static。
问题详情
在开发模式(DEBUG=True)下,将服务部署到带有分支对应前置路径的Docker主机时,无法正常加载静态文件,使用Python 4.0.6版本。
初始配置(settings.py)
DEBUG = True BASE_DIR = Path(__file__).resolve().parent.parent # 默认生成配置 FORCE_SCRIPT_NAME = "https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/" INSTALLED_APPS = [ ... 'django.contrib.staticfiles', ] STATIC_URL = 'static/' STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', )
HTML模板代码
{% load static %} <html> <head> ... <link rel="stylesheet" href="{% static 'tableau_explorer/style.css' %}">
静态文件路径
django_root/tableau_explorer/static/tableau_explorer
现象
- 本地开发机(未配置
FORCE_SCRIPT_NAME)无论直接运行manage.py还是Docker部署,静态文件均正常加载。 - 部署到目标Docker主机后,生成的HTML代码为:
<link rel="stylesheet" href="/static/tableau_explorer/style.css">
访问该路径出现404错误。
- 若修改
STATIC_URL为完整路径:STATIC_URL = 'https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/'
此时请求URL变为http://https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/tableau_explorer/style.css,返回HTML错误页面而非CSS,服务器提示:
Request Method: GET Request URL: http://https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/tableau_explorer/style.css Using the URLconf defined in bi_web.urls, Django tried these URL patterns, in this order: admin/ .... The current path, static/tableau_explorer/style.css, didn’t match any of these.
尝试过的方法
在主项目urls.py中添加以下代码,但无效果:
from django.conf import settings from django.contrib.staticfiles.urls import staticfiles_urlpatterns urlpatterns = [ . . . . ] if settings.DEBUG: urlpatterns += staticfiles_urlpatterns()
访问https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/时,收到错误信息“Directory indexes are not allowed here.”;访问staticx/这类不存在的路径则显示页面未找到,推测static模块已运行,但无法确认文件是否被正确收集。
进入运行中的Docker主机执行命令:
$ python manage.py findstatic tableau_explorer/style.css Found 'tableau_explorer/style.css' here: /code/tableau_explorer/static/tableau_explorer/style.css
确认static能找到目标文件。
疑问
若无法直接给出解决方案,希望了解开发模式下staticfiles的处理逻辑与服务机制:
- 是否应该拦截所有以
static/开头的请求? - 应用启动时,staticfiles是否会从各应用的
static文件夹收集.css文件并复制到可验证的磁盘存储?能否开启详细日志?在运行的服务器上能否在特定目录看到这些文件? - BASE_DIR配置是否与staticfiles相关?当前使用
manage.py createproject生成的默认配置。 - 当前的staticfiles是否会自动在URL中添加
static?是否无需修改urls.py?
编辑补充
发布问题后,在settings.py中添加STATIC_ROOT=/static,并在Dockerfile中添加collectstatic命令。进入运行中的Docker镜像查看:
$ ls -l /static/tableau_explorer/style.css
文件存在且权限正常。
此时渲染后的HTML代码为:
<link rel="stylesheet" href="https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/tableau_explorer/style.css">
直接访问该链接时,Django提示路径不匹配,推测需要在urls.py中配置相关规则让staticfiles处理这些请求。
访问时的响应内容:
<html lang="en"><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Page not found at /static/tableau_explorer/style.css</title> </head> <body> <div id="summary"> <h1>Page not found <span>(404)</span></h1> <table class="meta"> <tbody><tr> <th>Request Method:</th> <td>GET</td> </tr> <tr> <th>Request URL:</th> <td>http://https://pmdocker01d.pm.local:8443/bi-web-utils/ta0624/static/tableau_explorer/style.css</td> </tr> </tbody></table> </div> <div id="info"> <p> Using the URLconf defined in <code>bi_web.urls</code>, Django tried these URL patterns, in this order: </p> <ol> . . . . 无"/static"相关规则 . . . </ol> <p> The current path, <code>static/tableau_explorer/style.css</code>, didn’t match any of these. </p> ....
内容的提问来源于stack exchange,提问作者Levin

