如何在Flask中提供静态文件
所以这很尴尬。 我有一个应用程序,我扔在一起Flask
,现在它只是提供一个静态的HTML页面,一些链接到CSS和JS。 而且我无法findFlask
描述的返回静态文件的位置。 是的,我可以使用render_template
但我知道数据不是模板化的。 我以为send_file
或url_for
是正确的,但我无法让这些工作。 与此同时,我正在打开文件,阅读内容,并安装适当的mimetype Response
:
import os.path from flask import Flask, Response app = Flask(__name__) app.config.from_object(__name__) def root_dir(): # pragma: no cover return os.path.abspath(os.path.dirname(__file__)) def get_file(filename): # pragma: no cover try: src = os.path.join(root_dir(), filename) # Figure out how flask returns static files # Tried: # - render_template # - send_file # This should not be so non-obvious return open(src).read() except IOError as exc: return str(exc) @app.route('/', methods=['GET']) def metrics(): # pragma: no cover content = get_file('jenkins_analytics.html') return Response(content, mimetype="text/html") @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def get_resource(path): # pragma: no cover mimetypes = { ".css": "text/css", ".html": "text/html", ".js": "application/javascript", } complete_path = os.path.join(root_dir(), path) ext = os.path.splitext(path)[1] mimetype = mimetypes.get(ext, "text/html") content = get_file(complete_path) return Response(content, mimetype=mimetype) if __name__ == '__main__': # pragma: no cover app.run(port=80)
有人想给这个代码示例或url? 我知道这将是简单的死亡。
首选的方法是使用nginx或其他Web服务器来提供静态文件; 他们将能够比Flask更有效地做到这一点。
但是,您可以使用send_from_directory
从目录发送文件,在某些情况下可以非常方便:
from flask import Flask, request, send_from_directory # set the project root directory as the static folder, you can set others. app = Flask(__name__, static_url_path='') @app.route('/js/<path:path>') def send_js(path): return send_from_directory('js', path) if __name__ == "__main__": app.run()
不要将send_file
或send_static_file
与用户提供的path一起使用。
send_static_file
例子:
from flask import Flask, request # set the project root directory as the static folder, you can set others. app = Flask(__name__, static_url_path='') @app.route('/') def root(): return app.send_static_file('index.html')
我相信你会find你所需要的: http : //flask.pocoo.org/docs/quickstart/#static-files
基本上你只需要在你的包的根目录下有一个“静态”文件夹,然后你可以使用url_for('static', filename='foo.bar')
或直接链接到http://example.com/静态/ foo.bar 。
编辑 :正如build议您可以直接使用'/static/foo.bar'
path, 但 url_for()
开销(性能明智)是相当低,使用它意味着你将能够轻松地自定义行为之后(更改文件夹,更改URLpath,将您的静态文件移动到S3等)。
你也可以,这是我最喜欢的,设置一个文件夹作为静态path,以便里面的文件是每个人都可以访问。
app = Flask(__name__, static_url_path='/static')
使用该设置,您可以使用标准的HTML:
<link rel="stylesheet" type="text/css" href="/static/style.css">
我使用(而且一直工作得很好)是一个“模板”目录和一个“静态”目录。 我将所有的.html文件/ Flask模板放在templates目录中,而static包含CSS / JS。 就我所知,render_template对通用的html文件工作正常,不pipe你使用Flask的模板语法的程度如何。 以下是我的views.py文件中的示例调用。
@app.route('/projects') def projects(): return render_template("projects.html", title = 'Projects')
只要确实要使用url_for(),当你想引用静态目录中的静态文件。 你可能最终会在html中的CSS / JS文件链接中这样做。 例如…
<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>
这里有一个“规范的”非正式烧瓶教程的链接 – 在这里有很多伟大的提示,以帮助你在地面运行。
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
你可以使用这个function:
send_static_file(filename)
内部使用的function将静态文件从静态文件夹发送到浏览器。
app = Flask(__name__) @app.route('/<path:path>') def static_file(path): return app.send_static_file(path)
基于其他答案的一个最简单的工作示例如下:
from flask import Flask, request app = Flask(__name__, static_url_path='') @app.route('/index/') def root(): return app.send_static_file('index.html') if __name__ == '__main__': app.run(debug=True)
用称为index.html的HTML:
<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> <div> <p> This is a test. </p> </div> </body> </html>
重要说明: index.html位于名为static的文件夹中,即<projectpath>
具有.py
文件, <projectpath>\static
具有html
文件。
如果您希望服务器在networking上可见,请使用app.run(debug=True, host='0.0.0.0')
编辑:如果要求显示文件夹中的所有文件,使用此
@app.route('/<path:path>') def static_file(path): return app.send_static_file(path)
这实质上是BlackMamba
的答案,所以给他们一个赞成。
如果你只是想移动你的静态文件的位置,那么最简单的方法是在构造函数中声明path。 在下面的例子中,我将我的模板和静态文件移动到一个名为web
的子文件夹中。
app = Flask(__name__, static_url_path='', static_folder='web/static', template_folder='web/templates')
-
static_url_path=''
从URL中删除任何前面的path(即默认/static
)。 -
static_folder='web/static'
会告诉Flask提供web/static
的文件。 -
template_folder='web/templates'
,类似地,这改变了模板文件夹。
使用这个方法,下面的URL将返回一个CSS文件:
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
最后,这是一个文件夹结构的快照,其中flask_server.py
是Flask实例:
对于创build下一个文件夹树的angular度+样板stream:
backend/ | |------ui/ | |------------------build/ <--'static' folder, constructed by Grunt | |--<proj |----vendors/ <-- angular.js and others here | |-- folders> |----src/ <-- your js | |----index.html <-- your SPA entrypoint |------<proj |------ folders> | |------view.py <-- Flask app here
我使用以下解决scheme:
... root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui", "build") @app.route('/<path:path>', methods=['GET']) def static_proxy(path): return send_from_directory(root, path) @app.route('/', methods=['GET']) def redirect_to_index(): return send_from_directory(root, 'index.html') ...
它有助于重新定义“静态”文件夹为自定义。
所以我得到的东西工作(基于@ user1671599答案),并希望与你们分享(我希望我做的正确,因为这是我的第一个应用程序在Python中)
所以根据@ user1671599答案我做到了这一点 –
项目结构:
server.py:
from server.AppStarter import AppStarter import os static_folder_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "client") app = AppStarter() app.register_routes_to_resources(static_folder_root) app.run(__name__)
AppStarter.py:
from flask import Flask, send_from_directory from flask_restful import Api, Resource from server.ApiResources.TodoList import TodoList from server.ApiResources.Todo import Todo class AppStarter(Resource): def __init__(self): self._static_files_root_folder_path = '' # Default is current folder self._app = Flask(__name__) # , static_folder='client', static_url_path='') self._api = Api(self._app) def _register_static_server(self, static_files_root_folder_path): self._static_files_root_folder_path = static_files_root_folder_path self._app.add_url_rule('/<path:file_relative_path_to_root>', 'serve_page', self._serve_page, methods=['GET']) self._app.add_url_rule('/', 'index', self._goto_index, methods=['GET']) def register_routes_to_resources(self, static_files_root_folder_path): self._register_static_server(static_files_root_folder_path) self._api.add_resource(TodoList, '/todos') self._api.add_resource(Todo, '/todos/<todo_id>') def _goto_index(self): return self._serve_page("index.html") def _serve_page(self, file_relative_path_to_root): return send_from_directory(self._static_files_root_folder_path, file_relative_path_to_root) def run(self, module_name): if module_name == '__main__': self._app.run(debug=True)
默认情况下,烧瓶使用“模板”文件夹来包含所有的模板文件(任何纯文本文件,但通常.html
或某种模板语言,如jinja2)和一个“静态”文件夹,以包含所有的静态文件即.js
.css
和你的图像)。
在你的routes
,你可以使用render_template()
来渲染一个模板文件(正如我上面所说,默认情况下它被放置在templates
文件夹中)作为你的请求的响应。 而在模板文件(通常是一个类似.html的文件),你可能会使用一些.js
和/或`.css'文件,所以我想你的问题是如何将这些静态文件链接到当前模板文件。
from flask import redirect, url_for ... @app.route('/', methods=['GET']) def metrics(): return redirect(url_for('static', filename='jenkins_analytics.html'))
这服务器在您的html文件中引用的所有文件(css&js …)。
如果你只是想打开一个文件,你可以使用app.open_resource()
。 所以读一个文件看起来就像
with app.open_resource('/static/path/yourfile'): #code to read the file and do something