Flask蓝图在蓝图中查找静态文件而非根目录
我有一个蓝图,它应该在根目录下寻找静态文件,但实际上没有找到。
假设我有一个叫做'frontend'的蓝图。这个'frontend'只传入了template_folder='frontend'。
即使我把静态文件放在/app/frontend/static/file.css下面,它也找不到。放在/app/static/file.css下面也不行。
控制台的网页服务器每次都显示'404',对于每个css或js静态文件都是这样。
不过,当我打印出url_maps时,确实有显示:
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
我这样初始化了register_blueprint('frontend')。
frontend = Blueprint('frontend', __name__,template_folder='templates')
我的视图中的index返回:
return render_template('frontend.html', pagination=pagination)
frontend.html
只能在/app/frontend/templates
中使用。
如果你把frontend.html
放在/app/templates
中,它也不能工作。即使你去掉了"template_folder"这个参数。
文件结构:
app
-app.py
--frontend
--frontend/templates contains: (frontend.html) (base.html) (errors/404.html)
--static
--static/css (bootstrap.min.css) (what I want to grab with url_for inside base.html)
2 个回答
在创建你的 Blueprint
时,试着加上 static_folder='static'
。
另外,你可以在 jinja 里使用 url_for
函数来输出你的静态文件路径。
{{ url_for(".static", filename="css/bootstrap.min.css") }}
1. 模板
每个 Flask 应用、蓝图和模块都有一个叫 jinja_loader
的东西。当你使用 render_template
来查找模板时,它会先在应用里找,然后再到每个蓝图里找,直到找到第一个存在的文件为止(可以参考 get_source 和 _iter_loader)。
jinja_loader
是根据对象路径和模板文件夹名称来构建的。例如,如果你的应用、蓝图或模块在 /home/www/myapp
(/usr/lib/python3.4/site-packages/myapp
)文件夹里,并且有一个 template
文件夹,那么完整的模板文件夹就是 /home/www/myapp/template
(/usr/lib/python3.4/site-packages/myapp/template
)。
这意味着如果你在应用的模板文件夹里有文件,那么即使你在蓝图里渲染模板,也能找到并渲染它。如果应用的模板文件夹里没有文件,但蓝图里有文件,它也会被渲染。因此,建议在蓝图中使用独特的模板前缀,以避免模板被覆盖(比如 flask_admin 使用 admin/
作为模板前缀)。
例如,对于扩展来说,这样可以在包中使用模板,并且如果需要的话,可以在你的应用中替换它(如果你只是想继承模板,需要给它一个新名字)。
2. URL 规则
规则没有任何蓝图前缀——在蓝图中,你只需将前缀和规则连接起来,然后直接使用它。
所以所有的 URL 规则会根据现有的规则来解析(可以参考另一个回答 https://stackoverflow.com/a/17146563/880326)。
你可以有相同的 URL 规则描述(比如 /static
和 /static
),但只能有一个端点。
3. 静态文件
对于应用来说,默认会有一个静态文件夹。对于蓝图,你需要添加 static_folder
参数。但是如果两个规则有相同的描述,那么默认情况下你无法从两个地方获取文件(不过用 一点代码可以做到)。
对于 Flask 应用、蓝图和模块,完整的静态文件夹依赖于 root_path
,而这个又依赖于 __name__
参数。
不过,如果你的蓝图没有 URL 前缀,最好设置一个不同的 static_url_path
,以避免出错。