807 Stimmen

Wie man statische Dateien in Flask bereitstellt

Also das ist peinlich. Ich habe eine Anwendung in Flask zusammengeworfen und derzeit dient sie nur dazu, eine einzelne statische HTML-Seite mit einigen Links zu CSS und JS bereitzustellen. Und ich kann nicht finden, wo in der Dokumentation Flask beschreibt, wie man statische Dateien zurückgibt. Ja, ich könnte render_template verwenden, aber ich weiß, dass die Daten nicht in Templates aufbereitet sind. Ich hätte gedacht, dass send_file oder url_for das Richtige wären, aber ich konnte diese nicht zum Laufen bringen. In der Zwischenzeit öffne ich die Dateien, lese den Inhalt und richte eine Response mit dem entsprechenden Mimetyp ein:

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)
        # Herausfinden, wie flask statische Dateien zurückgibt
        # Versucht:
        # - render_template
        # - send_file
        # Das sollte nicht so unklar sein
        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('/')
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)

Kann mir jemand ein Code-Beispiel oder eine URL dafür geben? Ich weiß, dass das total einfach sein wird.

50voto

Kevin Busch Punkte 712

Was ich benutze (und es funktioniert großartig), ist ein "templates"-Verzeichnis und ein "static"-Verzeichnis. Ich platziere alle meine .html-Dateien/Flask-Templates im templates-Verzeichnis, und static enthält CSS/JS. render_template funktioniert meiner Kenntnis nach gut für generische HTML-Dateien, unabhängig vom Umfang, in dem du die Flask-Templating-Syntax verwendet hast. Unten ist ein Beispielaufruf in meiner views.py-Datei.

@app.route('/projects')
def projects():
    return render_template("projects.html", title = 'Projects')

Stelle nur sicher, dass du url_for() verwendest, wenn du tatsächlich auf eine statische Datei im separaten static-Verzeichnis verweisen möchtest. Du wirst wahrscheinlich ohnehin dies in deinen CSS/JS-Dateilinks in HTML machen. Zum Beispiel...

Hier ist ein Link zum "kanonischen" informellen Flask-Tutorial - hier findest du viele großartige Tipps, um sofort loszulegen.

http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

46voto

EpicPandaForce Punkte 75417

Ein einfachstes Arbeitsbeispiel basierend auf den anderen Antworten sieht wie folgt aus:

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)

Mit dem HTML namens index.html:

    Hallo Welt!

        Dies ist ein Test.

WICHTIG: Und index.html befindet sich in einem Ordner namens static, was bedeutet, dass die .py Datei hat und \static die html Datei hat.

Wenn Sie möchten, dass der Server im Netzwerk sichtbar ist, verwenden Sie app.run(debug=True, host='0.0.0.0')

BEARBEITEN: Um alle Dateien im Ordner anzuzeigen, wenn angefordert, verwenden Sie dies

@app.route('/')
def static_file(path):
    return app.send_static_file(path)

Was im Wesentlichen die Antwort von BlackMamba ist, also geben Sie ihnen ein Upvote.

18voto

kore666 Punkte 1541

Für den Angular+Boilerplate-Flow, der den nächsten Ordnerbaum erstellt:

backend/
|
|------ui/
|      |------------------build/          <--'static' Ordner, erstellt von Grunt
|      |--   |----src/       <-- deine js-Dateien
|                         |----index.html <-- dein SPA-Einstiegspunkt
|------
|
|------view.py  <-- Flask-App hier

Ich verwende folgende Lösung:

...
root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui", "build")

@app.route('/', 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 hilft dabei, den 'static' Ordner individuell neu zu definieren.

11voto

Novak254 Punkte 459
app = Flask(__name__, static_folder="Ihr statischer Ordnerpfad")

Wenn Sie Vorlagen in Ihrem Stammverzeichnis haben, wird das Platzieren des app=Flask(name) funktionieren, wenn die Datei, die dies enthält, sich auch am gleichen Speicherort befindet. Wenn sich diese Datei an einem anderen Ort befindet, müssen Sie den Vorlagenort angeben, um Flask zu ermöglichen, auf den Ort zu verweisen.

10voto

danfromisrael Punkte 2826

Also, ich habe es zum Laufen gebracht (basierend auf der Antwort von @user1671599) und wollte es mit euch teilen.

(Ich hoffe, ich mache es richtig, da es meine erste App in Python ist)

Ich habe Folgendes gemacht -

Projektstruktur:

Gib hier eine Bildbeschreibung ein

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 = ''  # Standardmäßig ist der aktuelle Ordner
        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('/', '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/')

    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)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X