Das ist also peinlich. Ich habe eine Anwendung, die ich in Flask
zusammengestellt habe, und derzeit wird nur eine einzige statische HTML-Seite mit Links zu CSS und JS bereitgestellt. Und ich kann nicht finden, wo in der Dokumentation Flask
beschrieben wird, wie statische Dateien zurückgegeben werden. Ja, ich könnte render_template
verwenden, aber ich weiß, dass die Daten nicht templatisiert sind. Ich hätte gedacht, dass send_file
oder url_for
das Richtige ist, aber ich konnte sie nicht zur Arbeit bringen. In der Zwischenzeit öffne ich die Dateien, lese den Inhalt und baue eine Response
mit dem entsprechenden Mimetyp auf:
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 __== '__main__': # pragma: no cover
app.run(port=80)
Jemand möchte dafür ein Codebeispiel oder eine URL angeben? Ich weiß, dass das einfach sein wird.
Die bevorzugte Methode ist die Verwendung von nginx oder einem anderen Webserver, um statische Dateien bereitzustellen. Sie können es effizienter als Flask tun.
Sie können jedoch auch send_from_directory
verwenden, um Dateien aus einem Verzeichnis zu senden.
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 __== "__main__":
app.run()
Verwenden Sie notsend_file
oder send_static_file
mit einem vom Benutzer angegebenen Pfad.
send_static_file
beispiel:
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')
Ich bin sicher, dass Sie dort finden, was Sie brauchen: http://flask.pocoo.org/docs/quickstart/#static-files
Im Grunde benötigen Sie nur einen "statischen" Ordner im Stammverzeichnis Ihres Pakets, und dann können Sie url_for('static', filename='foo.bar')
verwenden oder direkt mit http://example.com/static/foo.bar eine Verknüpfung zu Ihren Dateien herstellen.
EDIT: Wie in den Kommentaren vorgeschlagen, können Sie direkt den '/static/foo.bar'
-URL-Pfad VERWENDEN, ABERurl_for()
-Overhead (in Bezug auf die Leistung) ist relativ gering, und die Verwendung bedeutet, dass Sie dies problemlos tun können Passen Sie das Verhalten anschließend an (Ändern Sie den Ordner, ändern Sie den URL-Pfad, verschieben Sie die statischen Dateien in S3 usw.).
Sie können auch, und das ist mein Favorit, einen Ordner als statischen Pfad festlegen, so dass die darin enthaltenen Dateien für jeden erreichbar sind.
app = Flask(__name__, static_url_path='/static')
Mit diesem Set können Sie das Standard-HTML verwenden:
<link rel="stylesheet" type="text/css" href="/static/style.css">
Wenn Sie nur den Speicherort Ihrer statischen Dateien verschieben möchten, können Sie die Pfade im Konstruktor am einfachsten deklarieren. Im folgenden Beispiel habe ich meine Vorlagen und statischen Dateien in einen Unterordner namens web
verschoben.
app = Flask(__name__,
static_url_path='',
static_folder='web/static',
template_folder='web/templates')
static_url_path=''
entfernt alle vorangegangenen Pfade von der URL (d. H Standardeinstellung /static
).static_folder='web/static'
teilt Flask mit, welche Dateien unter web/static
gefunden werden sollen.template_folder='web/templates'
, in ähnlicher Weise ändert sich der Ordner __.-Vorlagen.Bei Verwendung dieser Methode gibt die folgende URL eine CSS-Datei zurück:
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
Zum Schluss noch ein Auszug der Ordnerstruktur, wobei flask_server.py
die Flask-Instanz ist:
Sie können diese Funktion verwenden:
send_static_file(filename)
Funktion, die intern verwendet wird, um statische Dateien aus dem statischen Ordner an den Browser zu senden.
app = Flask(__name__)
@app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
Was ich benutze (und es hat großartig funktioniert) ist ein "Vorlagen" -Verzeichnis und ein "statisches" Verzeichnis. Ich stelle alle meine .html-Dateien/Flask-Vorlagen in das Vorlagenverzeichnis und statisch enthält CSS/JS. render_template funktioniert nach meinem Wissen für generische HTML-Dateien, unabhängig davon, in welchem Umfang Sie die Flask-Schablonensyntax verwendet haben. Unten finden Sie einen Beispielaufruf in meiner views.py-Datei.
@app.route('/projects')
def projects():
return render_template("projects.html", title = 'Projects')
Stellen Sie einfach sicher, dass Sie url_for () verwenden, wenn Sie auf eine statische Datei im separaten statischen Verzeichnis verweisen möchten. Sie werden dies wahrscheinlich ohnehin in Ihren CSS/JS-Dateilinks in HTML tun. Zum Beispiel...
<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>
Hier ist ein Link zum "kanonischen" informellen Flask-Tutorial. Hier finden Sie viele nützliche Tipps, die Ihnen dabei helfen werden, den Boden zu öffnen.
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
Ein einfachstes Arbeitsbeispiel basierend auf den anderen Antworten ist das Folgende:
from flask import Flask, request
app = Flask(__name__, static_url_path='')
@app.route('/index/')
def root():
return app.send_static_file('index.html')
if __== '__main__':
app.run(debug=True)
Mit dem HTML-Code namens index.html:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<div>
<p>
This is a test.
</p>
</div>
</body>
</html>
WICHTIG: Und index.html befindet sich in einem Ordner mit dem Namen static . <projectpath>
hat die .py
-Datei und <projectpath>\static
die html
-Datei.
Wenn der Server im Netzwerk sichtbar sein soll, verwenden Sie app.run(debug=True, Host='0.0.0.0')
EDIT: Verwenden Sie diese Option, um alle Dateien im Ordner anzuzeigen, wenn Sie dazu aufgefordert werden
@app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
Was im Wesentlichen BlackMamba
s Antwort ist, also geben Sie ihnen eine positive Bewertung.
Für den Winkel + Boilerplate-Fluss, der den nächsten Ordnerbaum erstellt:
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
Ich verwende folgende Lösung:
...
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')
...
Es ist hilfreich, den "statischen" Ordner in benutzerdefiniert zu definieren.
Also habe ich die Dinge zum Laufen gebracht (basierend auf der Antwort von @ user1671599) und wollte sie mit euch teilen.
(Ich hoffe, ich mache es richtig, da es meine erste App in Python ist.)
Ich tat dies -
Projektstruktur:
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)
Gedanken zum Teilen ... dieses Beispiel.
from flask import Flask
app = Flask(__name__)
@app.route('/loading/')
def hello_world():
data = open('sample.html').read()
return data
if __== '__main__':
app.run(Host='0.0.0.0')
Das funktioniert besser und einfacher.
from flask import redirect, url_for
...
@app.route('/', methods=['GET'])
def metrics():
return redirect(url_for('static', filename='jenkins_analytics.html'))
Dieser Server enthält alle Dateien (css & js ...), auf die in Ihrer HTML-Datei verwiesen wird.
Alle Antworten sind gut, aber was für mich gut funktioniert hat, ist die einfache Funktion send_file
von Flask. Dies funktioniert gut, wenn Sie nur eine HTML-Datei als Antwort senden müssen, wenn Host: port/ApiName die Ausgabe von anzeigt die Datei im Browser
@app.route('/ApiName')
def ApiFunc():
try:
return send_file('some-other-directory-than-root/your-file.extension')
except Exception as e:
logging.info(e.args[0])```
Wenn Sie nur versuchen, eine Datei zu öffnen, können Sie app.open_resource()
verwenden. Das Lesen einer Datei würde ungefähr so aussehen
with app.open_resource('/static/path/yourfile'):
#code to read the file and do something
Eine der einfachen Möglichkeiten. Prost!
demo.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
if __== '__main__':
app.run(debug = True)
Erstellen Sie nun einen Ordnernamen mit dem Namen templates . Fügen Sie Ihre index.html -Datei in templates folder hinzu.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Python Web Application</title>
</head>
<body>
<div>
<p>
Welcomes You!!
</p>
</div>
</body>
</html>
Projektstruktur
-demo.py
-templates/index.html
Standardmäßig verwendet flask einen "Vorlagen" -Ordner für alle Ihre Vorlagendateien (alle Nur-Text-Dateien, aber normalerweise .html
oder eine Art von Vorlagensprache wie "jinja2") und einen "statischen" Ordner, der alle Ihre statischen Dateien enthält (dh .js
.css
und Ihre Bilder).
In Ihrer routes
können Sie render_template()
zum Rendern einer Vorlagendatei verwenden (wie ich oben sage, diese wird standardmäßig im Ordner templates
abgelegt) als Antwort für Ihre Anfrage. Und in der Vorlagendatei (normalerweise eine .html-ähnliche Datei) können Sie einige .js
- und/oder `.css'-Dateien verwenden. Ich denke, Ihre Frage ist, wie Sie diese statischen Dateien mit der aktuellen Vorlagendatei verknüpfen.