Comment servir des fichiers statiques dans un flacon
donc c'est embarrassant. J'ai une application que j'ai créée dans Flask
et pour l'instant il ne sert qu'une seule page HTML statique avec des liens vers CSS et JS. Et je ne trouve pas où dans la documentation Flask
décrit le retour de fichiers statiques. Oui, je pourrais utiliser render_template
mais je sais que les données ne sont pas templatisées. Je pensais que send_file
ou url_for
était la bonne chose, mais je n'ai pas pu les faire fonctionner. En attendant, je suis de l'ouverture de la fichiers, lecture de contenu, et montage d'un Response
avec mimetype approprié:
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 __name__ == '__main__': # pragma: no cover
app.run(port=80)
Quelqu'un veut donner un exemple de code ou une url pour cela? Je sais que cela va être simple.
13 réponses
la méthode préférée est d'utiliser nginx ou un autre serveur web pour servir des fichiers statiques; ils seront en mesure de le faire plus efficacement que Flask.
cependant, vous pouvez utiliser send_from_directory
pour envoyer des fichiers à partir d'un répertoire, ce qui peut être assez pratique dans certaines situations:
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 __name__ == "__main__":
app.run()
Faire pas utiliser send_file
ou send_static_file
avec une fourni par l'utilisateur chemin.
send_static_file
exemple:
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')
je suis sûr que vous trouverez ce dont vous avez besoin là: http://flask.pocoo.org/docs/quickstart/#static-files
fondamentalement, vous avez juste besoin d'un dossier" statique "à la racine de votre paquet, et alors vous pouvez utiliser url_for('static', filename='foo.bar')
ou lien direct à vos fichiers avec http://example.com/static/foo.bar .
EDIT : comme suggéré dans les commentaires, vous pouvez directement utiliser le '/static/foo.bar'
Le chemin D'URL mais url_for()
" overhead (performance wise) est assez faible, et l'utiliser signifie que vous serez en mesure de facilement personnaliser le comportement après (changer le dossier, changer le chemin D'URL, déplacer vos fichiers statiques à S3, etc).
vous pouvez également, et c'est mon préféré, définir un dossier comme chemin statique de sorte que les fichiers à l'intérieur sont accessibles pour tout le monde.
app = Flask(__name__, static_url_path='/static')
avec cet ensemble, vous pouvez utiliser le HTML standard:
<link rel="stylesheet" type="text/css" href="/static/style.css">
ce que j'utilise (et cela fonctionne très bien) est un répertoire" templates "et un répertoire" statique". Je place tout mon .les fichiers html/Flacon de modèles à l'intérieur du répertoire de modèles et statique contient CSS/JS. render_template fonctionne très bien pour les fichiers html génériques à ma connaissance, indépendamment de la mesure dans laquelle vous avez utilisé la syntaxe de templating de Flask. Ci-dessous est un exemple d'appel dans mon views.py fichier.
@app.route('/projects')
def projects():
return render_template("projects.html", title = 'Projects')
assurez-vous d'utiliser url_for() lorsque vous voulez faire référence certains fichiers statiques dans le répertoire statique. Vous finirez probablement par le faire de toute façon dans les liens de vos fichiers CSS/JS en html. Par exemple...
<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>
voici un lien vers le tutoriel" canonique " flasque informelle - beaucoup de bons conseils ici pour vous aider à atteindre le point de départ.
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
vous pouvez utiliser cette fonction:
send_static_file(filename)
Fonction utilisée en interne pour envoyer statique fichiers du dossier statique vers le navigateur.
app = Flask(__name__)
@app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
un exemple de travail le plus simple basé sur les autres réponses est le suivant:
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)
avec L'index HTML appelé .html :
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<div>
<p>
This is a test.
</p>
</div>
</body>
</html>
IMPORTANT: et index.html est dans un dossier appelé statique , ce qui signifie <projectpath>
a le fichier .py
, et <projectpath>\static
a le fichier html
.
Si vous voulez que le serveur soit visible sur le réseau, utilisez app.run(debug=True, host='0.0.0.0')
EDIT: pour afficher tous les fichiers dans le dossier si demandé, utilisez ce
@app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
qui est essentiellement la réponse de BlackMamba
, donnez-leur donc une note positive.
si vous voulez simplement déplacer l'emplacement de vos fichiers statiques, alors la méthode la plus simple est de déclarer les chemins dans le constructeur. Dans l'exemple ci-dessous, j'ai déplacé mes modèles et des fichiers statiques dans un sous-dossier appelé web
.
app = Flask(__name__,
static_url_path='',
static_folder='web/static',
template_folder='web/templates')
-
static_url_path=''
supprime tout chemin précédent de l'URL (i.e. la valeur par défaut/static
). -
static_folder='web/static'
va dire flasque servir les fichiers trouvés àweb/static
. -
template_folder='web/templates'
, de même, cela change la le dossier de modèles.
en utilisant cette méthode, L'URL suivante retournera un fichier CSS:
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
et enfin, voici un claquement de la structure du dossier, où flask_server.py
est l'instance du flacon:
pour flux angulaire+boilerplate qui crée l'arbre de dossiers suivant:
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
j'utilise la solution suivante:
...
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')
...
cela aide à redéfinir le dossier 'statique' à personnalisé.
donc j'ai fait marcher les choses (basé sur @user1671599 answer) et j'ai voulu le partager avec vous les gars.
(j'espère que je le fais bien puisque c'est ma première application en Python)
j'ai fait cela -
structure du projet:
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)
from flask import redirect, url_for
...
@app.route('/', methods=['GET'])
def metrics():
return redirect(url_for('static', filename='jenkins_analytics.html'))
ce serveur contient tous les fichiers (css & js... référencé dans votre fichier html.
par défaut, utilisez un dossier" templates "pour contenir tous vos fichiers de template(n'importe quel fichier en texte clair, mais habituellement .html
ou une sorte de langage de template tel que jinja2) et un dossier" statique "pour contenir tous vos fichiers statiques(i.e. .js
.css
et vos images).
Dans votre routes
, vous pouvez utiliser render_template()
pour rendre un fichier de modèle (comme je l'ai dit ci-dessus, par défaut il est placé dans le dossier templates
) comme réponse pour votre demande. Et dans le fichier de modèle (c'est généralement une .html fichier), u peut utiliser certains .js
et/ou".les fichiers de css, donc je suppose que votre question Est comment u lier ces fichiers statiques au fichier de modèle actuel.
Si vous essayez juste d'ouvrir un fichier, vous pouvez utiliser app.open_resource()
. Donc lire un fichier ressemblerait à quelque chose comme
with app.open_resource('/static/path/yourfile'):
#code to read the file and do something
la Pensée de partage.... cet exemple.
from flask import Flask
app = Flask(__name__)
@app.route('/loading/')
def hello_world():
data = open('sample.html').read()
return data
if __name__ == '__main__':
app.run(host='0.0.0.0')
cela fonctionne mieux et simple.