Hard-coded URLs break when routes change; url_for keeps links correct everywhere.
url_for(endpoint, **values) builds a URL from an endpoint name (the view function's name by default) and its route variables:
url_for("show_post", post_id=7) # '/posts/7'
url_for("search", q="flask", page=2) # '/search?q=flask&page=2'Arguments that are not route variables become the query string, and values are URL-encoded for you. Pass _external=True for an absolute URL with scheme and host, which you need in emails.
Why bother instead of writing "/posts/7"? You can change a route's path in one place, and every link and redirect follows. Misspelled endpoints fail loudly with BuildError rather than producing broken links.
url_for needs to know the current app, so call it inside a view, a template, or a with app.test_request_context(): block.
Static files go in a static/ folder and are served at /static/... by the dev server under the endpoint static:
<link rel="stylesheet" href="{{ url_for('static', filename='css/site.css') }}">In production, let the web server (Nginx) or a CDN serve them directly, since that is much faster than going through Python.
Combine redirect with url_for for navigation: return redirect(url_for("login")). After a successful form POST, always redirect (the Post/Redirect/Get pattern) so a browser refresh doesn't resubmit the form.
Example
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.get("/posts/<int:post_id>")
def show_post(post_id):
return f"post {post_id}"
@app.get("/latest")
def latest():
return redirect(url_for("show_post", post_id=7))
with app.test_request_context():
print(url_for("show_post", post_id=3)) # /posts/3
print(url_for("show_post", post_id=3, ref="mail")) # /posts/3?ref=mail
print(url_for("show_post", post_id=3, _external=True)) # http://localhost/posts/3
print(url_for("static", filename="css/site.css")) # /static/css/site.css
print(app.test_client().get("/latest").headers["Location"]) # /posts/7Remember
- url_for(endpoint, **values) builds URLs; extra values become the query string
- Static files live in static/ and are linked with url_for('static', filename=...)
- Redirect after a successful POST (Post/Redirect/Get)
Watch out for
- Hard-coding paths in templates, which silently break when a route changes.