Skip to main content
Flask Basics Tutorial
CHAPTER 05 Beginner

Flask Routing Basics

Updated: May 14, 2026
20 min read

# CHAPTER 5

Flask Routing Basics

1. Introduction

In the previous chapter, we mapped a single URL (/) to a specific Python function. But a real web application is a massive web of interconnected pages. How do you handle a blog with 5,000 articles? You certainly cannot write 5,000 separate @app.route decorators. In this chapter, we will master Routing. We will learn how to create multiple static routes, capture dynamic data from the URL (like a user's ID), and restrict routes to specific HTTP methods (GET vs. POST).

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define multiple static routes within a single application.
  • Create dynamic routes that capture variables from the URL.
  • Use type converters (<int:id>) to validate URL parameters.
  • Restrict routes to specific HTTP methods using methods=['GET', 'POST'].

3. Beginner-Friendly Explanation

Imagine working at the post office sorting facility.
  • Static Routing: A letter arrives addressed to "The Mayor." You know exactly which bin to put it in because there is only one Mayor. (@app.route('/about')).
  • Dynamic Routing: A letter arrives addressed to "Citizen #402". You don't have a specific bin for every single citizen. Instead, you have a general "Citizens" conveyor belt. You pull the number "402" off the envelope and hand it to the delivery driver, saying, "Take this to whoever is number 402." (@app.route('/user/<id>')).

Dynamic routing allows one single Python function to handle millions of different URLs automatically.

4. Step 1: Multiple Static Routes

Let's expand our app.py to handle standard website pages.
python
1234567891011121314151617
from flask import Flask
app = Flask(__name__)

@app.route(&#039;/')
def home():
    return "Homepage"

@app.route(&#039;/about')
def about():
    return "About Our Company"

@app.route(&#039;/contact')
def contact():
    return "Contact Us: support@example.com"

if __name__ == &#039;__main__':
    app.run(debug=True)

*You can define as many static routes as you want. Flask reads the URL and triggers the matching function.*

5. Step 2: Dynamic Routes (Capturing Variables)

If we want to display a user's profile, we use angle brackets < > in the route to capture the data and pass it into the function as an argument.
python
12345
# The <username> part acts as a wildcard
@app.route(&#039;/profile/<username>')
def profile(username):
    # The URL data is passed into the function!
    return f"<h1>Welcome to your profile, {username}!</h1>"

*Test it! Visit http://127.0.0.1:5000/profile/alice. The browser prints "Welcome to your profile, alice!" Visit /profile/bob, and it prints "bob". One function handles infinite URLs.*

6. Step 3: URL Type Converters

By default, dynamic routes capture data as strings. What if you are looking up a product by its ID number? If a user types /product/hello, your database will crash when it searches for an ID of "hello". We can force Flask to only accept integers using a type converter.
python
1234
# Force the 'post_id' to be an integer
@app.route(&#039;/post/<int:post_id>')
def show_post(post_id):
    return f"Viewing Blog Post #{post_id}"

*If a user visits /post/5, it works perfectly. If they visit /post/apple, Flask automatically blocks it and returns a 404 Not Found error!*

Common Converters:

  • <string:name> (Default) Accepts any text without a slash.
  • <int:id> Accepts positive integers.
  • <float:price> Accepts positive floating point values.

7. Step 4: HTTP Methods (GET vs POST)

By default, every @app.route only responds to GET requests (when a user types a URL into their browser). If a user tries to submit an HTML form (a POST request) to that URL, Flask will reject it with a "405 Method Not Allowed" error. We must explicitly tell Flask to accept POST requests.
python
1234
# Allow both GET (viewing the page) and POST (submitting a form)
@app.route(&#039;/login', methods=['GET', 'POST'])
def login():
    return "Login Page (Ready to receive data!)"

*(We will learn how to extract the actual form data in Chapter 7).*

8. Backend Workflow: Trailing Slashes

Pay close attention to trailing slashes in your routes.
  • @app.route('/about') (No trailing slash): If a user visits /about/ (with a slash), Flask returns a 404 error.
  • @app.route('/about/') (With trailing slash): If a user visits /about (no slash), Flask magically redirects them to /about/.

*Best Practice: Always include the trailing slash for major pages (/projects/) so users don't encounter 404 errors if they type it in manually.*

9. Best Practices

  • Route Naming Conventions: The name of your Python function (e.g., def show_post():) should be clear and unique. This function name is internally registered as the "Endpoint Name." Later, we will use this Endpoint Name to dynamically generate links in our HTML, preventing broken links if URL paths change.

10. Common Mistakes

  • Function Name Collisions: A very common beginner mistake is writing two different routes but accidentally giving the Python functions the exact same name.
python
1234567
@app.route(&#039;/home')
def index():
    return "Home"

@app.route(&#039;/about')
def index(): # ERROR! Function name already exists!
    return "About"

*Flask will crash with an AssertionError. Every View function must have a unique name.*

11. Exercises

  1. 1. Trace the Request flow: A user types http://127.0.0.1:5000/product/99. Explain chronologically how the number 99 is extracted from the URL and passed into the Python logic.

12. Coding Challenges

  • Challenge: In app.py, write a new dynamic route: /calculator/<int:num1>/<int:num2>. The View function should accept both numbers as arguments, add them together, and return a string displaying the result (e.g., "The sum is 10"). Test it in your browser.

13. MCQs with Answers

Question 1

What is the syntax used in a Flask route decorator to capture a dynamic section of the URL and enforce that it must be a whole number?

Question 2

By default, a Flask route created with @app.route('/submit') will only respond to which HTTP method?

14. Interview Questions

  • Q: Explain the concept of URL Type Converters in Flask. How do they act as a first layer of security and input validation before the data ever reaches the controller logic?
  • Q: Contrast a GET request with a POST request. In a web application, provide a specific scenario where you would explicitly configure a Flask route using methods=['POST'].

15. FAQs

Q: Can I make a dynamic route optional? A: Yes! You can stack decorators on top of a single function and provide a default argument.
python
1234
@app.route(&#039;/page/')
@app.route(&#039;/page/<int:num>')
def view_page(num=1):
    return f"Viewing page {num}"

16. Summary

In Chapter 5, we mastered Flask's routing engine. We scaled our application from a single page to a multi-page site by defining multiple static routes. We learned how to capture dynamic URL parameters using angle brackets (< >) and enforced data integrity using type converters like int. Finally, we introduced the concept of HTTP methods, preparing our routes to handle form submissions securely.

17. Next Chapter Recommendation

Currently, we are returning plain text strings. Real websites return complex HTML documents. Proceed to Chapter 6: Flask Templates with Jinja2.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·