So this is embarrassing. I’ve got an application that I threw together in Flask and for now it is just serving up a single static HTML page with some links to CSS and JS. And I can’t find where in the documentation Flask describes returning static files. Yes, I could use render_template but I know the data is not templatized. I’d have thought send_file or url_for was the right thing, but I could not get those to work. In the meantime, I am opening the files, reading content, and rigging up a Response with appropriate mimetype:
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)
Someone want to give a code sample or url for this? I know this is going to be dead simple.
from flask importFlask, 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()
千万不能使用send_file或send_static_file与用户提供的路径。
send_static_file 例:
from flask importFlask, 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')
The preferred method is to use nginx or another web server to serve static files; they’ll be able to do it more efficiently than Flask.
However, you can use send_from_directory to send files from a directory, which can be pretty convenient in some 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()
Do not use send_file or send_static_file with a user-supplied path.
send_static_file example:
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')
If you just want to move the location of your static files, then the simplest method is to declare the paths in the constructor. In the example below, I have moved my templates and static files into a sub-folder called web.
Basically you just need a “static” folder at the root of your package, and then you can use url_for('static', filename='foo.bar') or directly link to your files with http://example.com/static/foo.bar.
EDIT: As suggested in the comments you could directly use the '/static/foo.bar' URL path BUTurl_for() overhead (performance wise) is quite low, and using it means that you’ll be able to easily customise the behaviour afterwards (change the folder, change the URL path, move your static files to S3, etc).
What I use (and it’s been working great) is a “templates” directory and a “static” directory. I place all my .html files/Flask templates inside the templates directory, and static contains CSS/JS. render_template works fine for generic html files to my knowledge, regardless of the extent at which you used Flask’s templating syntax. Below is a sample call in my views.py file.
@app.route('/projects')
def projects():
return render_template("projects.html", title = 'Projects')
Just make sure you use url_for() when you do want to reference some static file in the separate static directory. You’ll probably end up doing this anyways in your CSS/JS file links in html. For instance…
Which is essentially BlackMamba‘s answer, so give them an upvote.
回答 7
对于创建下一个文件夹树的角度+样板流:
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
from server.AppStarterimportAppStarterimport 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__)
from flask importFlask
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')
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')
This works better and simple.
回答 11
使用redirect和url_for
from flask import redirect, url_for
@app.route('/', methods=['GET'])def metrics():return redirect(url_for('static', filename='jenkins_analytics.html'))
app = Flask(__name__, static_folder="your path to static")
If you have templates in your root directory, placing the app=Flask(name) will work if the file that contains this also is in the same location, if this file is in another location, you will have to specify the template location to enable Flask to point to the location
All the answers are good but what worked well for me is just using the simple function send_file from Flask. This works well when you just need to send an html file as response when host:port/ApiName will show the output of the file in browser
By default, flask use a “templates” folder to contain all your template files(any plain-text file, but usually .html or some kind of template language such as jinja2 ) & a “static” folder to contain all your static files(i.e. .js.css and your images).
In your routes, u can use render_template() to render a template file (as I say above, by default it is placed in the templates folder) as the response for your request. And in the template file (it’s usually a .html-like file), u may use some .js and/or `.css’ files, so I guess your question is how u link these static files to the current template file.
回答 16
如果您只是尝试打开文件,则可以使用 app.open_resource()。所以读取文件看起来像
with app.open_resource('/static/path/yourfile'):#code to read the file and do something