如何在Flask中提供静态文件

所以这很尴尬。 我有一个应用程序,我扔在一起Flask ,现在它只是提供一个静态的HTML页面,一些链接到CSS和JS。 而且我无法findFlask描述的返回静态文件的位置。 是的,我可以使用render_template但我知道数据不是模板化的。 我以为send_fileurl_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_filesend_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