Flask蓝图在蓝图中查找静态文件而非根目录

4 投票
2 回答
6852 浏览
提问于 2025-04-18 14:28

我有一个蓝图,它应该在根目录下寻找静态文件,但实际上没有找到。

假设我有一个叫做'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 个回答

0

在创建你的 Blueprint 时,试着加上 static_folder='static'

另外,你可以在 jinja 里使用 url_for 函数来输出你的静态文件路径。

{{ url_for(".static", filename="css/bootstrap.min.css") }}

4

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,以避免出错。

撰写回答