Statische Dateien in Flask - robot.txt, sitemap.xml (mod_wsgi)

94

Gibt es eine clevere Lösung, um statische Dateien im Anwendungsstammverzeichnis von Flask zu speichern? robots.txt und sitemap.xml werden voraussichtlich in / gefunden, daher war meine Idee, Routen für sie zu erstellen:

@app.route('/sitemap.xml', methods=['GET'])
def sitemap():
  response = make_response(open('sitemap.xml').read())
  response.headers["Content-type"] = "text/plain"
  return response

Es muss etwas Bequemeres geben :)

biesiad
quelle

Antworten:

78

Der beste Weg ist, static_url_path auf root url zu setzen

from flask import Flask

app = Flask(__name__, static_folder='static', static_url_path='')
DNS
quelle
Erwähnenswert ist, dass sich der Ordner static_folder nicht im Projektordner befinden muss. zB static_folder = '/ app / ui' ist in Ordnung.
Ashic
66

@vonPetrushev ist richtig, in der Produktion möchten Sie statische Dateien über Nginx oder Apache bereitstellen, aber für die Entwicklung ist es schön, wenn Ihre Entwicklungsumgebung einfach ist und Ihre Python-App auch den statischen Inhalt bereitstellt, damit Sie sich keine Sorgen machen müssen über das Ändern von Konfigurationen und mehrere Projekte. Dazu möchten Sie die SharedDataMiddleware verwenden .

from flask import Flask
app = Flask(__name__)
'''
Your app setup and code
'''
if app.config['DEBUG']:
    from werkzeug import SharedDataMiddleware
    import os
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
      '/': os.path.join(os.path.dirname(__file__), 'static')
    })

In diesem Beispiel wird davon ausgegangen, dass sich Ihre statischen Dateien im Ordner "static" befinden. Passen Sie sie an Ihre Umgebung an.

Philip Southam
quelle
1
VIELEN DANK! Das habe ich gebraucht! Ich möchte dies für mein Produktionsheroku tun. Siehe die Antworten auf dem folgenden Thread: flask.pocoo.org/mailinglist/archive/2012/2/22/…
David
2
Heads up - es gibt jetzt einen einfacheren Weg, damit umzugehen. Überprüfen Sie meine Antwort.
Sean McSomething
1
Gibt es eine Möglichkeit für die SharedDataMiddleware, nur '/' in index.html oder ähnliches aufzulösen?
Gromgull
63

Die sauberste Antwort auf diese Frage ist die Antwort auf diese (identische) Frage :

from flask import Flask, request, send_from_directory
app = Flask(__name__, static_folder='static')    

@app.route('/robots.txt')
@app.route('/sitemap.xml')
def static_from_root():
    return send_from_directory(app.static_folder, request.path[1:])

Zusammenfassen:

  • Wie David betonte, ist es mit der richtigen Konfiguration in Ordnung , ein paar statische Dateien über prod bereitzustellen
  • Das Suchen nach /robots.txt sollte nicht zu einer Umleitung zu /static/robots.txt führen. (In Seans Antwort ist nicht sofort klar, wie das erreicht wird.)
  • Es ist nicht sauber, statische Dateien zum App-Stammordner hinzuzufügen
  • Schließlich sieht die vorgeschlagene Lösung viel sauberer aus als der Ansatz des Hinzufügens von Middleware:
bebbi
quelle
22

Obwohl dies eine alte beantwortete Frage ist, beantworte ich diese Frage, da dieser Beitrag in den Google-Ergebnissen ziemlich weit oben steht. Wenn Sie die API-Dokumente für den Flask Application-Objektkonstruktor lesen, wird dies zwar in der Dokumentation nicht behandelt. Durch Übergeben des benannten Parameters static_folderwie folgt:

from flask import Flask
app = Flask(__name__,
            static_folder="/path/to/static",
            template_folder="/path/to/templates")

... können Sie festlegen, woher statische Dateien geliefert werden. Ebenso können Sie einen template_folderNamen für Sie definieren static_url_path.

Sean McSomething
quelle
@chmike Ja, standardmäßig ist dies der Fall, /staticaber Sie können dies durch Überschreiben ändern static_url_path.
Sean McSomething
Dies ist richtig, aber andere Antworten sind flexibler. Dieser ist durch die Tatsache begrenzt, dass er nur einen Verzeichnispfad bedienen kann.
Thomas Dignan
Dies ist nicht die Antwort auf die ursprüngliche Frage.
Paolo Casciello
2
Wenn Sie static_url_path auf "" setzen, können Sie Dateien aus / bereitstellen.
Beau
Dies zwingt Flask, statische Dateien bereitzustellen. Was ist, wenn Sie möchten, dass Nginx oder Apache ihnen dienen?
Markon
15

Das Bereitstellen statischer Dateien hat nichts mit Anwendungen zu tun, die dynamische Inhalte bereitstellen sollen. Die richtige Art der Bereitstellung statischer Dateien hängt davon ab, welchen Server Sie verwenden. Wenn Sie Ihre App zum Laufen bringen, müssen Sie sie schließlich an einen Webserver binden. Ich kann nur für Apache httpd sprechen, daher ist die Art und Weise, wie statische Dateien bereitgestellt werden, auf dem virtuellen Host definiert, den Sie über mod-wsgi an Ihre Anwendung binden. In der folgenden Anleitung erfahren Sie, wie Sie Sitemaps, robots.txt oder statische Inhalte bereitstellen : http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site

vonPetrushev
quelle
Das ist die Antwort, nach der ich gesucht habe. Vielen Dank!
Biesiad
1
Eine Anwendung soll Inhalte liefern, einige dynamische und einige statische.
Dem Pilafian
14

Eine andere Möglichkeit, statische Dateien zu senden, besteht darin, eine Sammelregel wie die folgende zu verwenden:

@app.route('/<path:path>')
def catch_all(path):
    if not app.debug:
        flask.abort(404)
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    return f.read()

Ich benutze dies, um zu versuchen, das Setup bei der Entwicklung zu minimieren. Ich habe die Idee von http://flask.pocoo.org/snippets/57/ bekommen.

Außerdem entwickle ich mit flask auf meinem eigenständigen Computer, stelle es jedoch mit Apache auf dem Produktionsserver bereit. Ich benutze:

file_suffix_to_mimetype = {
    '.css': 'text/css',
    '.jpg': 'image/jpeg',
    '.html': 'text/html',
    '.ico': 'image/x-icon',
    '.png': 'image/png',
    '.js': 'application/javascript'
}
def static_file(path):
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    root, ext = os.path.splitext(path)
    if ext in file_suffix_to_mimetype:
        return flask.Response(f.read(), mimetype=file_suffix_to_mimetype[ext])
    return f.read()

[...]

if __name__ == '__main__':
    parser = optparse.OptionParser()
    parser.add_option('-d', '--debug', dest='debug', default=False,
                      help='turn on Flask debugging', action='store_true')

    options, args = parser.parse_args()

    if options.debug:
        app.debug = True
        # set up flask to serve static content
        app.add_url_rule('/<path:path>', 'static_file', static_file)
    app.run()
Ben Golding
quelle
1
Heads up - es gibt jetzt einen einfacheren Weg, damit umzugehen. Überprüfen Sie meine Antwort.
Sean McSomething
Hervorragende Möglichkeit, wenn Sie mehrere Pfade bedienen müssen!
Thomas Dignan
6

Dies könnte hinzugefügt worden sein, seit diese Frage gestellt wurde, aber ich habe die "helpers.py" von flask durchgesehen und flask.send_from_directory gefunden:

send_from_directory(directory, filename, **options)
'''
  send_from_directory(directory, filename, **options)
  Send a file from a given directory with send_file.  This
  is a secure way to quickly expose static files from an upload folder
  or something similar.
'''

... die auf flask.send_file verweisen:

send_file(filename_or_fp, mimetype=None, as_attachment=False, attachment_filename=None, add_etags=True, cache_timeout=43200, conditional=False)

... was für mehr Kontrolle besser zu sein scheint, obwohl send_from_directory ** Optionen direkt an send_file weiterleitet.

blast_hardcheese
quelle
3

Aus der Dokumentation hier: http://flask.pocoo.org/docs/quickstart/#static-files

Dynamische Webanwendungen benötigen ebenfalls statische Dateien. Dort kommen normalerweise die CSS- und JavaScript-Dateien her. Idealerweise ist Ihr Webserver so konfiguriert, dass er sie für Sie bereitstellt, aber während der Entwicklung kann Flask dies auch tun. Erstellen Sie einfach einen Ordner mit dem Namen static in Ihrem Paket oder neben Ihrem Modul, der in der Anwendung unter / static verfügbar ist.

Verwenden Sie den speziellen 'statischen' URL-Namen, um URLs zu diesem Teil der URL zu generieren:

url_for ('static', filename = 'style.css')

Die Datei muss im Dateisystem als static / style.css gespeichert werden.

Josh Klein
quelle
0

Ich habe auch das gleiche Dilemma. Habe etwas gesucht und meine Antwort gefunden (MHO):

Könnte auch aus der Dokumentation zitieren

Dynamische Webanwendungen benötigen ebenfalls statische Dateien. Dort kommen normalerweise die CSS- und JavaScript-Dateien her. Idealerweise ist Ihr Webserver so konfiguriert, dass er sie für Sie bereitstellt, aber während der Entwicklung kann Flask dies auch tun . Erstellen Sie einfach einen Ordner mit dem Namen static in Ihrem Paket oder neben Ihrem Modul, der in der Anwendung unter / static verfügbar ist.

IMHO: Wenn Ihre Anwendung für die Produktion bereit ist, sollte die Bereitstellung statischer Dateien auf dem Webserver (nginx, apache) konfiguriert sein (oder ist idealerweise). aber während der Entwicklung stellte Flask es jedoch zur Verfügung, um statische Dateien bereitzustellen. Dies soll Ihnen helfen, sich schnell zu entwickeln - Sie müssen keine Webserver und dergleichen einrichten.

Ich hoffe es hilft.

jpanganiban
quelle
0

Versuche dies:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Farzad Amirjavid
quelle