File statici in Flask: robot.txt, sitemap.xml (mod_wsgi)


94

Esiste una soluzione intelligente per archiviare file statici nella directory principale dell'applicazione di Flask. robots.txt e sitemap.xml dovrebbero essere trovati in /, quindi la mia idea era di creare percorsi per loro:

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

Deve esserci qualcosa di più conveniente :)

Risposte:


78

Il modo migliore è impostare static_url_path sull'URL di root

from flask import Flask

app = Flask(__name__, static_folder='static', static_url_path='')

Vale la pena ricordare che static_folder non deve essere nella cartella del progetto. es. static_folder = '/ app / ui' va bene.
ashic

66

@vonPetrushev ha ragione, in produzione vorrai servire file statici tramite nginx o apache, ma per lo sviluppo è bello avere il tuo ambiente di sviluppo semplice con la tua app Python che serve anche il contenuto statico, quindi non devi preoccuparti sulla modifica delle configurazioni e di più progetti. Per farlo, ti consigliamo di utilizzare SharedDataMiddleware .

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')
    })

Questo esempio presume che i tuoi file statici siano nella cartella "static", adattati a ciò che si adatta al tuo ambiente.


1
GRAZIE! Questo è ciò di cui avevo bisogno! Sto cercando di farlo per la mia produzione heroku. Vedi le risposte nel seguente thread: flask.pocoo.org/mailinglist/archive/2012/2/22/…
David

2
Attenzione: c'è un modo più semplice per gestirlo ora. Controlla la mia risposta.
Sean McSomething

1
C'è un modo per SharedDataMiddleware di risolvere solo "/" in index.html o simili?
Gromgull

63

La risposta più pulita a questa domanda è la risposta a questa domanda (identica) :

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:])

Riassumere:

  • come ha sottolineato David, con la configurazione corretta va bene servire alcuni file statici tramite prod
  • la ricerca di /robots.txt non dovrebbe comportare un reindirizzamento a /static/robots.txt. (Nella risposta di Seans non è immediatamente chiaro come sia stato ottenuto.)
  • non è pulito aggiungere file statici nella cartella principale dell'app
  • infine, la soluzione proposta sembra molto più pulita dell'approccio di aggiunta del middleware:

22

Anche se questa è una vecchia domanda con risposta, rispondo a questa perché questo post è piuttosto alto nei risultati di Google. Anche se non è trattato nella documentazione, se leggi i documenti API per il costruttore di oggetti dell'applicazione Flask è coperto. Passando il parametro denominato in questo static_foldermodo:

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

... puoi definire da dove vengono serviti i file statici. Allo stesso modo, puoi definire un template_folder, il tuo nome static_url_path.


@chmike sì, il valore predefinito è /staticma puoi cambiarlo sovrascrivendo static_url_path.
Sean McSomething

Questo è corretto, ma altre risposte sono più flessibili. Questo è limitato dal fatto che può servire solo un percorso di directory.
Thomas Dignan

Questa non è la risposta alla domanda originale.
Paolo Casciello

2
Se imposti static_url_path su "" puoi servire file da /.
Beau

Ciò costringe Flask a servire file statici. E se vuoi che nginx o apache li servano?
Markon

15

Il servizio di file statici non ha nulla a che fare con un'applicazione destinata a fornire contenuto dinamico. Il modo corretto di servire i file statici dipende dal server che stai utilizzando. Dopo tutto, quando la tua app sarà attiva e funzionante, dovrai associarla a un server web. Posso parlare solo per apache httpd, quindi il modo di servire i file statici è definito nell'host virtuale che stai vincolando alla tua applicazione tramite mod-wsgi. Ecco la guida che ti mostrerà come offrire sitemap, robots.txt o qualsiasi contenuto statico: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site


Questa è la risposta che stavo cercando. Grazie!
biesiad

1
Un'applicazione ha lo scopo di fornire contenuti, alcuni dinamici e altri statici.
Dem Pilafian

14

Un altro modo per inviare file statici è utilizzare una regola generale come questa:

@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()

Lo uso per cercare di ridurre al minimo la configurazione durante lo sviluppo. Ho avuto l'idea da http://flask.pocoo.org/snippets/57/

Inoltre, sto sviluppando utilizzando flask sulla mia macchina autonoma ma distribuendo con Apache nel server di produzione. Io uso:

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()

1
Attenzione: c'è un modo più semplice per gestirlo ora. Controlla la mia risposta.
Sean McSomething

Ottimo modo se devi servire più percorsi!
Thomas Dignan

6

Questo potrebbe essere stato aggiunto da quando è stata posta questa domanda, ma stavo cercando in "helpers.py" di flask e ho trovato flask.send_from_directory:

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.
'''

... che fa riferimento a flask.send_file:

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

... che sembra migliore per un maggiore controllo, sebbene send_from_directory passi ** le opzioni direttamente a send_file.


3

Dalla documentazione qui: http://flask.pocoo.org/docs/quickstart/#static-files

Anche le applicazioni web dinamiche richiedono file statici. Di solito è da lì che provengono i file CSS e JavaScript. Idealmente il tuo server web è configurato per servirli per te, ma durante lo sviluppo Flask può farlo anche tu. Basta creare una cartella chiamata static nel tuo pacchetto o accanto al tuo modulo e sarà disponibile in / static sull'applicazione.

Per generare URL per quella parte dell'URL, utilizza lo speciale nome URL "statico":

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

Il file deve essere memorizzato nel filesystem come static / style.css.


0

Anch'io sto avendo lo stesso dilemma. Ho fatto qualche ricerca e ho trovato la mia risposta (MHO):

Tanto vale citare dalla documentazione

Anche le applicazioni web dinamiche richiedono file statici. Di solito è da lì che provengono i file CSS e JavaScript. Idealmente il tuo server web è configurato per servirli per te, ma durante lo sviluppo Flask può farlo anche tu . Basta creare una cartella chiamata static nel tuo pacchetto o accanto al tuo modulo e sarà disponibile in / static sull'applicazione.

IMHO: Quando la tua applicazione è in produzione , il file serving statico dovrebbe essere (o idealmente) configurato sul server web (nginx, apache); ma durante lo sviluppo , Flask lo ha reso disponibile per servire file statici. Questo per aiutarti a svilupparti rapidamente, senza bisogno di configurare server web e simili.

Spero che sia d'aiuto.


0

Prova questo:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.