Flask:子目录中的静态文件

15 投票
1 回答
19442 浏览
提问于 2025-04-17 16:53

在我的Flask模板文件中,我这样引入一个CSS文件(省略了基础部分):

url_for('static', filename='css/bootstrap.css')

这段代码会变成 /static/css/bootstrap.css,这意味着(因为前面有斜杠)它被解释为 domain.com/static/css/bootstrap.css。可惜的是,实际的 static 文件夹是在一个子目录下:domain.com/projects/test/static/

环境具体信息:

我的fcgi文件位于 ~/fcgi-bin 文件夹中(我想这和主机有关):

$ cat ~/fcgi-bin/test.fcgi
#!/usr/bin/env python2.7

import sys
sys.path.insert(0, "/home/abcc/html/projects/test")

from flup.server.fcgi import WSGIServer
from app import app

class ScriptNameStripper(object):
   def __init__(self, app):
       self.app = app

   def __call__(self, environ, start_response):
       environ['SCRIPT_NAME'] = ''
       return self.app(environ, start_response)

app = ScriptNameStripper(app)

if __name__ == '__main__':
    WSGIServer(app).run()

而我的 .htaccess 文件位于 domain.com/projects/test/ 目录下。

$ cat .htaccess 
<IfModule mod_fcgid.c>
   AddHandler fcgid-script .fcgi
   <Files ~ (\.fcgi)>
       SetHandler fcgid-script
       Options +FollowSymLinks +ExecCGI
   </Files>
</IfModule>

<IfModule mod_rewrite.c>
   Options +FollowSymlinks
   RewriteEngine On
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)$ /fcgi-bin/test.fcgi/$1 [QSA,L]
</IfModule>

总结一下,我希望 url_for('static', filename='css/bootstrap.css') 返回 static/css/bootstrap.css,而不是 /static/css/bootstrap.css

编辑 #1

我注意到这种情况也发生在普通的 url_for 调用上,而不仅仅是静态文件,比如 url_for('about')。

编辑 #2

我写了一个 快速入门应用一篇博客文章 来讲解这个问题。

1 个回答

10

不要把脚本名称设置为空字符串,试着把它设置为'/projects/test'。如果把SCRIPT_NAME设置为空字符串,应用程序会认为它是在域名的根目录下运行,这样通过url_for生成的路径就会从根目录开始。设置脚本名称为'/projects/test'后,url_for('static', filename='/foo/bar.css')会返回'/projects/test/static/foo/bar.css'

如果你确实想让你的应用的静态资源在不同的端点上提供服务,那你就得自己实现一些东西,像这样:

from flask import Flask
from os.path import join

app = Flask(__name__)

def url_for_static(filename):
    root = app.config.get('STATIC_ROOT', '')
    return join(root, filename)

撰写回答