100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Routing in Flask

Understand how @app.route binds URLs to view functions, how dynamic URL converters validate input, and how to handle HTTP methods and generate URLs with url_for.

Flask FoundationsBeginner9 min readJul 10, 2026
Analogies

Defining Routes with @app.route

The @app.route decorator binds a URL path to a view function, registering it in Flask's underlying Werkzeug URL map; when a request matches the path, Flask calls that function and uses its return value (a string, tuple, or Response object) to build the HTTP response.

🏏

Cricket analogy: @app.route binding a URL to a function is like a fielding chart assigning Jasprit Bumrah specifically to bowl the death overs — a fixed mapping the captain refers to the moment that situation arises.

Dynamic URL Converters

Flask supports variable segments in routes using angle-bracket syntax like /user/<username> or typed converters such as /post/<int:post_id>, /page/<float:score>, and /files/<path:subpath>; these converters validate and coerce the URL segment before passing it as an argument to the view function, so an invalid type (e.g., a string where <int:post_id> expects digits) results in a 404 rather than reaching your code.

🏏

Cricket analogy: A typed converter like <int:post_id> is like a stadium's ticket scanner rejecting a fake ticket before a fan even reaches the turnstile, so only valid entries reach the seating area (the view function).

HTTP Methods and url_for

By default a route only accepts GET requests; passing methods=["GET", "POST"] to @app.route allows a view to handle form submissions, and inside the function request.method distinguishes which verb was used; rather than hardcoding URLs in templates or redirects, Flask's url_for("view_name", **kwargs) builds the correct URL dynamically from the route definition, so renaming a path later doesn't break every hardcoded link.

🏏

Cricket analogy: Checking request.method to branch GET vs POST logic is like an umpire distinguishing between a no-ball call and a wide call — same delivery moment, different rule applied based on what actually happened.

python
@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"Post #{post_id}"

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        return "Logging in..."
    return "Login form"

# In a template or redirect:
url_for("show_post", post_id=42)  # -> "/post/42"

Flask automatically adds a HEAD handler wherever GET is allowed, and OPTIONS is handled automatically too unless you disable it — you rarely need to declare these explicitly.

  • @app.route registers a URL pattern in Werkzeug's URL map, tied to a view function.
  • Angle-bracket converters like <int:id> or <path:subpath> validate and coerce URL segments.
  • An invalid converter match (e.g., letters for <int:...>) results in a 404, not a crash in your view.
  • Routes accept GET by default; add methods=['GET','POST'] to handle form submissions.
  • request.method lets a single view branch logic based on the HTTP verb used.
  • url_for() generates URLs from view names, avoiding brittle hardcoded links.

Practice what you learned

Was this page helpful?

Topics covered

#Python#FlaskStudyNotes#WebDevelopment#RoutingInFlask#Routing#Flask#Defining#Routes#StudyNotes#SkillVeris