How to set static_url_path in Flask application
Flask creates the URL route when you create the Flask()
object. You'll need to re-add that route:
# remove old static map
url_map = app.url_map
try:
for rule in url_map.iter_rules('static'):
url_map._rules.remove(rule)
except ValueError;
# no static view was created yet
pass
# register new; the same view function is used
app.add_url_rule(
app.static_url_path + '/<path:filename>',
endpoint='static', view_func=app.send_static_file)
It'll be easier just to configure your Flask()
object with the correct static URL path.
Demo:
>>> from flask import Flask
>>> app = Flask(__name__)
>>> app.url_map
Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
>>> app.static_url_path = '/PREFIX/static'
>>> url_map = app.url_map
>>> for rule in url_map.iter_rules('static'):
... url_map._rules.remove(rule)
...
>>> app.add_url_rule(
... app.static_url_path + '/<path:filename>',
... endpoint='static', view_func=app.send_static_file)
>>> app.url_map
Map([<Rule '/PREFIX/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
The accepted answer is correct, but slightly incomplete. It is true that in order to change the static_url_path
one must also update the app's url_map
by removing the existing Rule
for the static
endpoint and adding a new Rule
with the modified url path. However, one must also update the _rules_by_endpoint
property on the url_map
.
It is instructive to examine the add()
method on the underlying Map
in Werkzeug. In addition to adding a new Rule
to its ._rules
property, the Map
also indexes the Rule
by adding it to ._rules_by_endpoint
. This latter mapping is what is used when you call app.url_map.iter_rules('static')
. It is also what is used by Flask's url_for()
.
Here is a working example of how to completely rewrite the static_url_path, even if it was set in the Flask app constructor.
app = Flask(__name__, static_url_path='/some/static/path')
a_new_static_path = '/some/other/path'
# Set the static_url_path property.
app.static_url_path = a_new_static_path
# Remove the old rule from Map._rules.
for rule in app.url_map.iter_rules('static'):
app.url_map._rules.remove(rule) # There is probably only one.
# Remove the old rule from Map._rules_by_endpoint. In this case we can just
# start fresh.
app.url_map._rules_by_endpoint['static'] = []
# Add the updated rule.
app.add_url_rule(f'{a_new_static_path}/<path:filename>',
endpoint='static',
view_func=app.send_static_file)
Just to complete the answer above, we also need to clear the view_functions that maps the endpoint with the delegate:
app.view_functions["static"] = None