C'est donc embarrassant. J'ai créé une application dans Flask
et, pour l'instant, elle 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 des fichiers statiques. Oui, je pourrais utiliser render_template
mais je sais que les données ne sont pas modélisées. J'aurais pensé que send_file
ou url_for
était la bonne chose, mais je ne pouvais pas les faire fonctionner. Entre-temps, j'ouvre les fichiers, lit le contenu et configure une Response
avec le type MIME 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 __== '__main__': # pragma: no cover
app.run(port=80)
Quelqu'un veut donner un exemple de code ou une URL pour cela? Je sais que ça va être très simple.
La méthode recommandée consiste à utiliser nginx ou un autre serveur Web pour servir des fichiers statiques. ils seront capables de le faire plus efficacement que Flask.
Cependant, vous pouvez utiliser send_from_directory
pour envoyer des fichiers depuis un répertoire, ce qui peut s'avérer très 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 __== "__main__":
app.run()
Utilisez not utilisez send_file
ou send_static_file
avec un chemin fourni par l'utilisateur.
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 y trouverez ce dont vous avez besoin: http://flask.pocoo.org/docs/quickstart/#static-files
En gros, vous avez simplement besoin d’un dossier "statique" à la racine de votre paquet, puis vous pouvez utiliser url_for('static', filename='foo.bar')
ou lier directement vos fichiers avec http://example.com/static/foo.bar .
EDIT: comme suggéré dans les commentaires, vous pouvez directement utiliser le chemin '/static/foo.bar'
de l'URL MAISurl_for()
est relativement faible (en termes de performances) et son utilisation signifie personnalisez ensuite le comportement (changez le dossier, changez le chemin de l'URL, déplacez vos fichiers statiques vers S3, etc.).
Vous pouvez également, et c'est mon préféré, définir un dossier en tant que chemin statique pour que les fichiers qu'il contient soient accessibles à tous.
app = Flask(__name__, static_url_path='/static')
Avec cet ensemble, vous pouvez utiliser le code HTML standard:
<link rel="stylesheet" type="text/css" href="/static/style.css">
Si vous souhaitez simplement déplacer l'emplacement de vos fichiers statiques, la méthode la plus simple consiste à déclarer les chemins dans le constructeur. Dans l'exemple ci-dessous, j'ai déplacé mes modèles et 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 (c'est-à-dire . le /static
par défaut).static_folder='web/static'
dira à Flask de servir les fichiers trouvés à web/static
.template_folder='web/templates'
, de même, cela change le dossier templates.En utilisant cette méthode, l'URL suivante renverra un fichier CSS:
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
Et enfin, voici un aperçu de la structure du dossier, où flask_server.py
est l'instance Flask:
Ce que j'utilise (et cela fonctionne très bien) est un répertoire "templates" et un répertoire "statique". Je place tous mes fichiers .html/modèles Flask dans le répertoire templates, et static contient CSS/JS. A ma connaissance, render_template fonctionne très bien pour les fichiers HTML génériques, quelle que soit la mesure dans laquelle vous avez utilisé la syntaxe de template de Flask. Vous trouverez ci-dessous un exemple d'appel dans mon fichier views.py.
@app.route('/projects')
def projects():
return render_template("projects.html", title = 'Projects')
Assurez-vous simplement d’utiliser url_for () lorsque vous souhaitez référencer un fichier statique dans le répertoire statique séparé. Vous finirez probablement par le faire de toute façon dans vos liens de fichiers CSS/JS au format HTML. Par exemple...
<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>
Voici un lien vers le didacticiel informel "canonique" de Flask - de nombreux conseils utiles pour vous aider à démarrer.
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
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 __== '__main__':
app.run(debug=True)
Avec le code HTML appelé index.html:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<div>
<p>
This is a test.
</p>
</div>
</body>
</html>
IMPORTANT: And index.html se trouve dans un dossier appelé static , ce qui signifie que <projectpath>
contient le fichier .py
et <projectpath>\static
le fichier html
.
Si vous souhaitez 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 du dossier si nécessaire, utilisez cette commande.
@app.route('/<path:path>')
def static_file(path):
return app.send_static_file(path)
Ce qui est essentiellement la réponse de BlackMamba
, donnez-leur un vote positif.
Pour un flux angulaire + passe-partout créant une arborescence de dossiers suivante:
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')
...
Il est utile de redéfinir le dossier 'statique' en un dossier personnalisé.
Je me suis donc mis au travail (à partir de la réponse @ user1671599) et je voulais le partager avec vous.
(J'espère que je le fais bien car c'est ma première application en Python)
J'ai fait ça -
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)
Pensée de partager .... cet exemple.
from flask import Flask
app = Flask(__name__)
@app.route('/loading/')
def hello_world():
data = open('sample.html').read()
return data
if __== '__main__':
app.run(Host='0.0.0.0')
Cela fonctionne mieux et simple.
from flask import redirect, url_for
...
@app.route('/', methods=['GET'])
def metrics():
return redirect(url_for('static', filename='jenkins_analytics.html'))
Cela sert tous les fichiers (css & js ...) référencés dans votre fichier html.
Toutes les réponses sont bonnes mais ce qui a bien fonctionné pour moi est d’utiliser la simple fonction send_file
de Flask. Cela fonctionne bien lorsque vous avez juste besoin d'envoyer un fichier HTML en réponse lorsque Host: port/ApiName affichera le résultat de le fichier dans le navigateur
@app.route('/ApiName')
def ApiFunc():
try:
return send_file('some-other-directory-than-root/your-file.extension')
except Exception as e:
logging.info(e.args[0])```
Si vous essayez simplement 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
Un des moyen simple de faire. Salut!
demo.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
if __== '__main__':
app.run(debug = True)
Créez maintenant un nom de dossier appelé templates . Ajoutez votre index.html fichier à l'intérieur de templates folder
index.html
<!DOCTYPE html>
<html>
<head>
<title>Python Web Application</title>
</head>
<body>
<div>
<p>
Welcomes You!!
</p>
</div>
</body>
</html>
Structure du projet
-demo.py
-templates/index.html
Par défaut, flask utilise un dossier "templates" pour contenir tous vos fichiers modèles (tout fichier en texte brut, mais généralement .html
ou une sorte de langage de modèle tel que jinja2) et un dossier "statique" pour contenir tous vos fichiers statiques (c'est-à-dire .js
.css
et vos images).
Dans votre routes
, vous pouvez utiliser render_template()
pour restituer un fichier de modèle (comme je le dis ci-dessus, par défaut, il est placé dans le dossier templates
) en tant que réponse à votre demande. Et dans le fichier de modèle (il s’agit généralement d’un fichier de type .html), vous pouvez utiliser des fichiers .js
et/ou `.css '. Votre question est donc de savoir comment vous liez ces fichiers statiques au fichier de modèle actuel.