URL Variables
Dynamic URLs let you capture parts of the path and use them in your function. Flask uses angle brackets to mark these segments:
@app.route("/user/")
def user_profile(name):
return f"Hello, {name}!"
Visit /user/alice and the name parameter receives "alice". By default, these are strings. But you can constrain the type:
@app.route("/post/")
def show_post(post_id):
return f"Viewing post #{post_id}"
If someone visits /post/abc, Flask returns a 404 because "abc" isn't an integer. This saves you from writing validation logic yourself.
You can use multiple variables in a single route:
@app.route("/user//post/")
def user_post(username, post_id):
return f"{username}'s post #{post_id}"
After a request is handled, you can access the captured variables through request.view_args:
from flask import request
@app.before_request
def log_route_params():
if request.view_args:
print("URL params:", request.view_args)
Here's a tip that will save you headaches: never hardcode URLs in your templates or redirects. Use url_for() instead. It takes an endpoint name and builds the URL for you:
from flask import url_for
@app.route("/")
def index():
# Instead of "/user/alice"
link = url_for("user_profile", name="alice")
return f'Go to <a href="{link}">Alice\'s profile</a>'
This is better because if you ever change a route's URL pattern, every url_for() call updates automatically. Hardcoded links break silently โ url_for() doesn't.
In templates, the same principle applies:
<a href="{{ url_for('user_profile', name='alice') }}">Alice</a>