Как обслуживать статические файлы в колбе
так что это неловко. У меня есть приложение, которое я бросил вместе в Flask
а пока он просто обслуживает одну статическую HTML-страницу с некоторыми ссылками на CSS и JS. И я не могу найти, где в документации Flask
описывает возврат статических файлов. Да, я мог бы использовать render_template
но я знаю, что данные не шаблонизированы. Я бы подумал send_file
или url_for
было правильно, но я не мог заставить их работать. Тем временем я открываю файлы, читаю содержимое и такелаж до Response
С соответствующим mimetype:
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 для этого? Я знаю, что это будет очень просто.
13 ответов:
предпочтительный метод-использовать nginx или другой веб-сервер для обслуживания статических файлов; они смогут сделать это более эффективно, чем 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()
Do не использовать
send_file
илиsend_static_file
с пользовательским путем.
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')
Я уверен, что вы найдете то, что вам нужно там:http://flask.pocoo.org/docs/quickstart/#static-files
В основном вам просто нужна "статическая" папка в корне вашего пакета, а затем вы можете использовать
url_for('static', filename='foo.bar')
или напрямую связать с вашими файлами с помощью http://example.com/static/foo.bar.EDIT: как было предложено в комментариях, вы можете напрямую использовать
'/static/foo.bar'
URL path ноurl_for()
накладные расходы (производительность мудрый) довольно низкий, и использование его означает, что вы сможете легко настроить поведение после этого (изменить папку, изменить путь URL, переместить статические файлы в S3 и т. д.).
вы также можете, и это мой любимый, установить папку в качестве статического пути, чтобы файлы внутри были доступны для всех.
app = Flask(__name__, static_url_path='/static')
С этим набором вы можете использовать стандартный HTML:
<link rel="stylesheet" type="text/css" href="/static/style.css">
то, что я использую (и он отлично работает), - это каталог "шаблоны" и "статический" каталог. Я размещаю все свои .html-файлы / Шаблоны Колб внутри каталога шаблонов, а статический содержит CSS / JS. насколько мне известно, render_template отлично работает для общих html-файлов, независимо от того, в какой степени вы использовали синтаксис шаблонов Flask. Ниже приведен пример вызова в моем views.py файл.
@app.route('/projects') def projects(): return render_template("projects.html", title = 'Projects')
просто убедитесь, что вы использовать url_for (), когда вы хотите ссылаться на статический файл в отдельный статический каталог. Вы, вероятно, в конечном итоге сделать это в любом случае в CSS/JS ссылки на файлы в html. Например...
<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
Вы можете использовать эту функцию :
send_static_file(filename)
Функция, используемая внутри для отправки статических данных файлы из статической папки в браузер.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)
С HTML называется .HTML-код:
<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> <div> <p> This is a test. </p> </div> </body> </html>
важно: и .HTML-код в папке статический, что означает
<projectpath>
имеет и<projectpath>\static
имеет .если вы хотите, чтобы сервер был виден в сети, используйте
app.run(debug=True, host='0.0.0.0')
EDIT: для отображения всех файлов в папке, если требуется, используйте это
@app.route('/<path:path>') def static_file(path): return app.send_static_file(path)
что по существу
BlackMamba
ответ, так что дайте им голосовать.
если вы просто хотите переместить расположение статических файлов, то самый простой способ-объявить пути в конструкторе. В приведенном ниже примере я переместил свои шаблоны и статические файлы в подпапку с именем
web
.app = Flask(__name__, static_url_path='', static_folder='web/static', template_folder='web/templates')
static_url_path=''
удаляет любой предыдущий путь из URL (т. е. значение по умолчанию/static
).static_folder='web/static'
скажет колба служить файлы, найденные наweb/static
.template_folder='web/templates'
аналогично, при этом меняется этот папка шаблонов.используя этот метод, следующий URL-адрес вернет файл CSS:
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
и, наконец, вот привязка структуры папок, где
flask_server.py
это экземпляр колбы:
для углового + шаблонного потока, который создает следующее дерево папок:
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
Я использую следующее решение:
... 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)
Я сделал это -
структура проекта:
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)
from flask import redirect, url_for ... @app.route('/', methods=['GET']) def metrics(): return redirect(url_for('static', filename='jenkins_analytics.html'))
это серверы всех файлов (css & js...) ссылка в вашем html-файле.
по умолчанию flask использует папку "шаблоны", чтобы содержать все ваши файлы шаблонов(любой текстовый файл, но обычно
.html
или какой-то язык шаблонов, такой как jinja2) и" статическая " папка, содержащая все ваши статические файлы (т. е..js
.css
и ваши изображения).
В вашемroutes
, вы можете использоватьrender_template()
для визуализации файла шаблона (как я уже говорил выше, по умолчанию он помещается в