Routing and URLs

Introduction

Routes connect URL paths to view functions. Flask supports static paths, dynamic segments, type converters, url_for for link generation, redirects, and abort for HTTP errors. This chapter covers patterns you need before Blueprints and REST APIs.

Prerequisites

Static Routes

Trailing slash behavior: /about/ vs /about—Flask can redirect; be consistent in links.

Dynamic Routes

python
@app.route("/user/<username>")
def user_profile(username):
    return f"Profile: {username}"
 
@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"Post ID: {post_id}"

Built-in converters:

ConverterExampleMatches
string (default)<name>Text without /
int<int:id>Positive integers
float<float:price>Floating point
path<path:filepath>Text including /
uuid<uuid:item_id>UUID strings

Custom converters are advanced—rare in starter projects.

url_for

Generate URLs by endpoint name (function name by default):

python
from flask import Flask, url_for
 
app = Flask(__name__)
 
@app.route("/user/<username>")
def user_profile(username):
    return f"User: {username}"
 
@app.route("/links")
def links_demo():
    profile_url = url_for("user_profile", username="alice")
    return f'<a href="{profile_url}">Alice</a>'

Code explanation:

  • Renaming routes does not break templates if you always use url_for
  • _external=True builds absolute URLs for emails

redirect

python
from flask import Flask, redirect, url_for
 
app = Flask(__name__)
 
@app.route("/old-about")
def old_about():
    return redirect(url_for("about"))
 
@app.route("/about")
def about():
    return "About page"

Permanent move (301):

python
return redirect(url_for("about"), code=301)

abort and Error Pages

python
from flask import Flask, abort
 
app = Flask(__name__)
 
@app.route("/item/<int:item_id>")
def item(item_id):
    if item_id < 1:
        abort(404)
    return f"Item {item_id}"

Custom error handlers (preview):

python
@app.errorhandler(404)
def not_found(e):
    return "Page not found", 404

Full error pages come in a later chapter.

RESTful Routing (Concept)

MethodPathAction
GET/usersList users
POST/usersCreate user
GET/users/<id>Get one
PUT/PATCH/users/<id>Update
DELETE/users/<id>Delete

Same path, different methods:

python
from flask import Flask, request
 
app = Flask(__name__)
 
@app.route("/users", methods=["GET", "POST"])
def users():
    if request.method == "POST":
        return "Create user", 201
    return "List users"

Dedicated REST chapter expands this pattern.

Blueprint URL Prefix (Preview)

Later, Blueprints mount under a prefix:

python
# Concept only — full chapter later
# bp = Blueprint("admin", __name__, url_prefix="/admin")
# /admin/dashboard → admin.dashboard view

FAQ

404 on valid route?

Check FLASK_APP, typos in decorator, or duplicate endpoint names.

Same function name twice?

Second route overwrites endpoint—use unique function names or endpoint= in @app.route.

url_for BuildError?

Missing route argument—pass all dynamic segments.

Order of routes matters?

More specific routes before catch-alls like /<path:slug>.

GET only by default?

@app.route allows GET only unless methods=[...] is set.

Trailing slash redirect?

strict_slashes=False on route to disable automatic redirects.