我有我的Django应用,并且有以下用例:
manage.py runserver
方法。因此,我希望我的应用可以在这种情况下正常工作。https://myserver.com/tool1
,https://myserver.com/tool2
等。因此,我想将我的应用程序置于这种结构中https://tool.myserver.com
但是当我尝试执行此操作时,我遇到了静态文件问题(叹气!),因为如果我将STATIC_URL
作为相对路径STATIC_URL='static/'
,则它不适用于“嵌套”页面(即,如果我在myserver.com/tool1/page
上,则静态URL将映射到myserver.com/tool1/page/static
,这是不正确的)。
另一方面,如果我使用绝对路径STATIC_URL='/static/'
,那么它对于情况2根本不起作用,因为Django应用程序不知道URL所在的/tool1
部分。
根据环境和硬编码STATIC_URL
,我可以为STATIC_URL='/tool1/static/'
使用两个不同的变体,但是对于情况3,相同的代码将不起作用...
我应该如何处理这种情况?
答案 0 :(得分:1)
从Django应用程序处理STATIC_URL
可能会导致开销。由于您有多个子目录,为什么不只从其中一个提供静态文件呢?提供静态文件时,不必与子目录匹配。
让我们说,如果您这样设置STATIC_URL
:
STATIC_URL = "/tool1/static/"
然后,您可以像这样配置NGINX
:
server {
listen 80
server_name *.myserver.com;
location /tool1/static/ {
root /path/to/STATIC_ROOT;
}
location / {
proxy_pass http://localhost:8000; # <-- No trailing slash to make it work with gunicorn
}
location /tool2/ {
proxy_pass http://localhost:8000;
proxy_set_header SCRIPT_NAME /tool2; # <-- For serving in sub path
}
location /tool1/ {
proxy_pass http://localhost:8000;
proxy_set_header SCRIPT_NAME /tool1; # <-- For serving in sub path
}
}
然后在设置中将STATIC_URL更新为/tool1/static/
。另外,请确保您的STATIC_ROOT
指向服务器中静态文件所在的正确路径。最后,在部署静态文件之前,您需要运行collectstatic command
将静态文件放入STATIC_ROOT
目录中,然后重新启动NGINX服务器。
更新:不建议使用硬编码的网址。相反,在模板中,您应该使用{% URL '<url_name> '%}
标签,或者在python代码中使用reverse()
。因此,django将自行解析网址。当它位于/tool1
位置时,URL将解析为/tool1/url_name/
,而当您处于位置/tool2/url_name
(基于/tool2
)时,URL将被解析为SCRIPT_NAME
。
答案 1 :(得分:0)
我建议将您的静态文件放在存储服务中,例如AWS S3,Google Cloud Storage等。 这样,无论您使用哪种网址(嵌套,子域等等),它都始终可用
示例设置(可能需要更多步骤):
更改您的settings.py
:
STATIC_URL = 'https://storage.googleapis.com/your_bucket/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
在部署应用程序之前,运行manage.py collectstatic --noinput
staticfiles
文件夹中的文件复制到存储服务,并确保它们是公开的我发现whitenoise
确实可以帮助静态文件大小和更容易部署
答案 2 :(得分:0)
似乎没有真正好的解决方法。但是,我发现了几种选择:
始终使用一个规范地址(个人首选)
我应该问自己“为什么要在https://myserver.com/tool1
和https://tool1.myserver.com
上都可以使用您的工具?”。实际上,我没有任何理由为什么要同时单独提供。因此,只需选择“规范”地址并设置适当的重定向:
如果域是规范的:
server_name myserver.com
location /tool1/ {
rewrite ^/tool1/?(.*)$ https://tool1.myserver.com/$1 permanent;
}
如果文件夹是规范的:
server_name tool1.myserver.com
location / {
rewrite ^ https://myserver.com/tool1$request_uri? permanent;
}
然后在后端使用与规范地址相对应的STATIC_URL的 one 选项(即/static
用于子域,/tool1/static
用于文件夹)
其他标题或URL参数
如果有理由(告诉我为什么!)不使用重定向并且同时使用两个地址,则如ruddra所述,可以添加其他标头,然后在后端使用它们以生成稍微不同的页面:
location /tool1/ {
<proxy_pass something>
proxy_set_header SCRIPT_NAME /tool1;
}
如果您选择文件夹作为规范地址,则可以使用相同的方法,那么您可能要避免在后端对tool1
进行硬编码。然后,也许您可以使用自定义标头或可以在后端处理的其他url参数,例如?from=domain
[1]。在这里我没有现成的解决方案,因为对我而言首选子域大小写。