web-dev-qa-db-fra.com

Fichiers statiques dans Flask - robot.txt, sitemap.xml (mod_wsgi)

Existe-t-il une solution intelligente pour stocker des fichiers statiques dans le répertoire racine de l'application de Flask. robots.txt et sitemap.xml devraient se trouver dans /, donc mon idée était de leur créer des routes:

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

Il doit y avoir quelque chose de plus pratique :)

89
biesiad

La meilleure façon est de définir static_url_path sur l'URL racine

from flask import Flask

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

@vonPetrushev a raison, en production, vous voudrez servir des fichiers statiques via nginx ou Apache, mais pour le développement, c'est bien d'avoir votre environnement de développement simple avec votre application python servant le contenu statique comme vous n'avez donc pas à vous soucier de changer les configurations et les projets multiples. Pour ce faire, vous voudrez utiliser le 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')
    })

Cet exemple suppose que vos fichiers statiques se trouvent dans le dossier "statique", ajustez-les en fonction de votre environnement.

65
Philip Southam

La réponse la plus nette à cette question est la réponse à cette (identique) question :

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

Résumer:

  • comme l'a souligné David, avec la bonne configuration, c'est ok pour servir quelques fichiers statiques via prod
  • la recherche de /robots.txt ne devrait pas entraîner de redirection vers /static/robots.txt. (Dans la réponse de Seans, il n'est pas immédiatement clair comment cela est réalisé.)
  • ce n'est pas propre d'ajouter des fichiers statiques dans le dossier racine de l'application
  • enfin, la solution proposée semble beaucoup plus propre que l'approche d'ajout de middleware:
56
bebbi

Même s'il s'agit d'une ancienne question à laquelle j'ai répondu, je réponds à cette question car ce message apparaît assez haut dans les résultats de Google. Bien que cela ne soit pas couvert dans la documentation, si vous lisez la documentation de l'API pour le constructeur Flask Application), il est couvert. En passant le paramètre nommé static_folder ainsi:

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

... vous pouvez définir la provenance des fichiers statiques. De même, vous pouvez définir un template_folder, votre nom static_url_path.

21
Sean McSomething

Servir des fichiers statiques n'a rien à voir avec une application destinée à fournir du contenu dynamique. La manière correcte de servir des fichiers statiques dépend du serveur que vous utilisez. Après tout, lorsque votre application sera opérationnelle, vous devrez la lier à un serveur Web. Je ne peux parler que pour Apache httpd, donc la façon de servir les fichiers statiques est définie dans l'hôte virtuel que vous liez à votre application via mod-wsgi. Voici le guide qui vous montrera comment diffuser des plans de site, robots.txt ou tout contenu statique: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site

15
vonPetrushev

Une autre façon d'envoyer des fichiers statiques consiste à utiliser une règle fourre-tout comme celle-ci:

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

J'utilise ceci pour essayer de minimiser la configuration lors du développement. J'ai eu l'idée de http://flask.pocoo.org/snippets/57/

De plus, je développe en utilisant flask sur ma machine autonome mais en déployant avec Apache dans le serveur de production. J'utilise:

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 __== '__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()
14
Ben Golding

Cela aurait pu être ajouté depuis que cette question a été posée, mais je regardais à travers "helpers.py" de flask et j'ai trouvé 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.
'''

... qui fait référence à flask.send_file:

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

... ce qui semble mieux pour plus de contrôle, bien que send_from_directory passe directement les options ** à send_file.

6
blast_hardcheese

De la documentation ici: http://flask.pocoo.org/docs/quickstart/#static-files

Les applications Web dynamiques ont également besoin de fichiers statiques. C’est généralement d’où proviennent les fichiers CSS et JavaScript. Idéalement, votre serveur Web est configuré pour les servir pour vous, mais pendant le développement Flask peut également le faire. Créez simplement un dossier appelé statique dans votre package ou à côté de votre module et il sera disponible at/statique sur l'application.

Pour générer des URL vers cette partie de l'URL, utilisez le nom d'URL "statique" spécial:

url_for ('statique', nom de fichier = 'style.css')

Le fichier doit être stocké sur le système de fichiers en tant que static/style.css.

3
Josh Klein

J'ai aussi le même dilemme. A fait quelques recherches et trouvé ma réponse (MHO):

Autant citer la documentation

Les applications Web dynamiques ont également besoin de fichiers statiques. C’est généralement d’où proviennent les fichiers CSS et JavaScript. Idéalement, votre serveur Web est configuré pour les servir pour vous, mais pendant le développement Flask peut également le faire. Créez simplement un dossier appelé static dans votre package ou à côté de votre module et il sera disponible sur/static sur l'application.

À mon humble avis: lorsque votre application est en place pour production, le service de fichiers statiques doit être (ou est idéalement) configuré sur le serveur Web (nginx, Apache); mais pendant développement, Flask l'a rendu disponible pour servir des fichiers statiques. C'est pour vous aider à vous développer rapidement - pas besoin de configurer des serveurs web et autres).

J'espère que ça aide.

0
jpanganiban