Reputation: 6091
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
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