18

I want to do something like this:

app = Flask(__name__)
app.config.from_object(mypackage.config)
app.static_url_path = app.config['PREFIX']+"/static"

when I try:

print app.static_url_path

I get the correct static_url_path

But in my templates when I use url_for('static'), The html file generated using jinja2 still has the default static URL path /static with the missing PREFIX that I added.

If I hardcode the path like this:

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

It works fine. What am I doing wrong?

4 Answers 4

12

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>])
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks it worked with slight modification. I had to set both static_url_path and static_folder to None when I initially create the FLask Object. And then add_url_rule. [I couldnt make it work by trying to remove the rules and then re add it as you mentioned in the solution]... Thanks a lot.
@user3873617: right, if you set static_folder to None then the rule will not be created in the first place.
Thanks @MartijnPieters. Is there a way to add such a prefix to all the routes defined for my application, not only to static?
@Patrick: You could use a Blueprint for all your routes and mount that blueprint with a prefix: app.register_blueprint(your_blueprint, url_prefix="/PREFIX").
6

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)

Comments

2

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

Comments

1

I think you missed static_folder

app = Flask(__name__)
app.config.from_object(mypackage.config)
app.static_url_path = app.config['PREFIX']+"/static"
app.static_folder = app.config['PREFIX']+"/static"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.