simple images files estaticos archivos python flask static-files

python - images - flask static files



Cómo servir archivos estáticos en matraz (13)

Así que esto es embarazoso. Tengo una aplicación que presenté en Flask y por ahora solo sirve una página HTML estática con algunos enlaces a CSS y JS. Y no puedo encontrar dónde en la documentación que Flask describe devolver archivos estáticos. Sí, podría usar render_template pero sé que los datos no están templados. send_file pensado que send_file o url_for era lo correcto, pero no podía hacer que funcionaran. Mientras tanto, abro los archivos, leo el contenido y preparo una Response con el tipo de mímeto apropiado:

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)

Alguien quiere dar una muestra de código o url para esto? Sé que esto va a ser muy simple.


Así que tengo las cosas funcionando (basadas en la respuesta de @ user1671599) y quería compartirlas con ustedes.

(Espero hacerlo bien ya que es mi primera aplicación en Python)

Hice esto -

Estructura del proyecto:

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)


De forma predeterminada, el matraz usa una carpeta de "plantillas" para contener todos sus archivos de plantilla (cualquier archivo de texto sin formato, pero generalmente .html o algún tipo de lenguaje de plantilla como jinja2) y una carpeta "estática" para contener todos sus archivos estáticos ( Es decir .js .css y sus imágenes).
En sus routes , puede usar render_template() para renderizar un archivo de plantilla (como he dicho anteriormente, por defecto se coloca en la carpeta de templates ) como la respuesta para su solicitud. Y en el archivo de plantilla (generalmente es un archivo tipo .html), u puede usar algunos archivos .js y / o .css, así que supongo que su pregunta es cómo vincular estos archivos estáticos al archivo de plantilla actual.


El método preferido es usar nginx u otro servidor web para servir archivos estáticos; Podrán hacerlo más eficientemente que Flask.

Sin embargo, puede usar send_from_directory para enviar archivos desde un directorio, lo que puede ser bastante conveniente en algunas situaciones:

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

No utilice send_file o send_static_file con una ruta proporcionada por el usuario.

Ejemplo de send_static_file :

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


Estoy seguro de que encontrará lo que necesita allí: http://flask.pocoo.org/docs/quickstart/#static-files

Básicamente solo necesita una carpeta "estática" en la raíz de su paquete, y luego puede usar url_for(''static'', filename=''foo.bar'') o directamente a sus archivos con http://example.com/static/foo.bar .

EDITAR : Como se sugiere en los comentarios, usted podría usar directamente la ruta URL ''/static/foo.bar'' PERO url_for() sobrecarga (en lo que url_for() rendimiento) es bastante baja, y su uso significa que podrá personalizar fácilmente el comportamiento después (cambie la carpeta, cambie la ruta de la URL, mueva sus archivos estáticos a S3, etc.).


Lo que uso (y ha funcionado muy bien) es un directorio de "plantillas" y un directorio "estático". Coloco todos mis archivos .html / plantillas de Flask dentro del directorio de plantillas, y static contiene CSS / JS. Según mi conocimiento, render_template funciona bien para archivos html genéricos, independientemente de la medida en que haya utilizado la sintaxis de plantilla de Flask. A continuación hay una llamada de muestra en mi archivo views.py.

@app.route(''/projects'') def projects(): return render_template("projects.html", title = ''Projects'')

Solo asegúrese de usar url_for () cuando quiera hacer referencia a algún archivo estático en el directorio estático separado. Probablemente termines haciendo esto de todos modos en tus enlaces de archivos CSS / JS en html. Por ejemplo...

<script src="{{ url_for(''static'', filename=''styles/dist/js/bootstrap.js'') }}"></script>

Aquí hay un enlace al tutorial informal "canónico" de Flask: aquí encontrará muchos consejos excelentes para ayudarlo a comenzar.

http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world


Para el flujo angular + repetitivo que crea el siguiente árbol de carpetas:

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

Uso la siguiente solución:

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

Ayuda a redefinir la carpeta ''estática'' para personalizarla.


Pensamiento de compartir .... este ejemplo.

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

Esto funciona mejor y simple.


Puede utilizar esta función:

send_static_file(filename)
Función utilizada internamente para enviar archivos estáticos desde la carpeta estática al navegador.

app = Flask(__name__) @app.route(''/<path:path>'') def static_file(path): return app.send_static_file(path)


Si solo está intentando abrir un archivo, puede usar app.open_resource() . Así que leer un archivo sería algo así como

with app.open_resource(''/static/path/yourfile''): #code to read the file and do something


Si solo quiere mover la ubicación de sus archivos estáticos, entonces el método más simple es declarar las rutas en el constructor. En el siguiente ejemplo, moví mis plantillas y archivos estáticos a una subcarpeta llamada web .

app = Flask(__name__, static_url_path='''', static_folder=''web/static'', template_folder=''web/templates'')

  • static_url_path='''' elimina cualquier ruta anterior de la URL (es decir, la predeterminada /static ).
  • static_folder=''web/static'' le indicará a Flask que sirva los archivos que se encuentran en web/static .
  • template_folder=''web/templates'' , de manera similar, esto cambia la carpeta de plantillas.

Usando este método, la siguiente URL devolverá un archivo CSS:

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">

Y finalmente, aquí hay un complemento de la estructura de carpetas, donde flask_server.py es la instancia de Flask:


También puede, y este es mi favorito, establecer una carpeta como ruta estática para que los archivos del interior sean accesibles para todos.

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

Con ese conjunto puedes usar el HTML estándar:

<link rel="stylesheet" type="text/css" href="/static/style.css">


Un ejemplo de trabajo más simple basado en las otras respuestas es el siguiente:

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)

Con el HTML llamado index.html :

<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> <div> <p> This is a test. </p> </div> </body> </html>

IMPORTANTE: Y index.html está en una carpeta llamada static , lo que significa que <projectpath> tiene el archivo .py , y <projectpath>/static tiene el archivo html .

Si desea que el servidor esté visible en la red, use app.run(debug=True, host=''0.0.0.0'')

EDITAR: para mostrar todos los archivos en la carpeta si así lo solicita, use este

@app.route(''/<path:path>'') def static_file(path): return app.send_static_file(path)

BlackMamba es esencialmente la respuesta de BlackMamba , así que dales un voto positivo.


from flask import redirect, url_for ... @app.route(''/'', methods=[''GET'']) def metrics(): return redirect(url_for(''static'', filename=''jenkins_analytics.html''))

Esto sirve todos los archivos (css y js ...) a los que se hace referencia en su archivo html.