Jakob Busk Sørensen
Jakob Busk Sørensen

Reputation: 6091

Flask routing and relative paths

I am making a website using Flask. It's utilizing a base template in HTML, which is used for all pages. In the base page (called base.html) there is some references to various static files. The references are using relative paths.

Here is a couple of examples from base.html:

<link rel="stylesheet" href="../static/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="../static/css/main.css">

This works fine, as long as I don't include input parameters in my route, but rather get them from requests like this:

@app.route('/person/delete')
def delete_person():
    id = request.args.get('id')
    # some more logic here...

However, if I change my route to include the input parameters, like this:

@app.route('/person/delete/<int:id>')
def delete_person(id):
    # some more logic here...

Then my relative path will fail. It seems that I am one level to deep, in the latter example. At least I get the following error in the log:

127.0.0.1 - - [29/Dec/2019 19:20:14] "GET /person/static/css/bootstrap-theme.min.css HTTP/1.1" 404 -
127.0.0.1 - - [29/Dec/2019 19:20:14] "GET /person/static/css/main.css HTTP/1.1" 404 -

The person part should not be a part of the URL, as the static folder is in the root level. Is there some clever way to counter this behavior?

Note: I could probably avoid relative paths in the base.html file and simply use some sort of shortcut to the base folder, but that would potentially mean that I can never use relative paths. That would be quite sad.

Upvotes: 2

Views: 8921

Answers (1)

VPfB
VPfB

Reputation: 17352

As mentioned in comments, url_for is the proper solution.

An example from other project:

<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='nnn.min.css') }}">

In general, url_for cannot be replaced by hardcoded URLs, not even absolute ones, because the whole Flask application may be deployed with a prefix in its base URL, e.g. https://www.example.com/appname. The appname is a part of the configuration and it is known only at runtime.

Upvotes: 5

Related Questions