Flask URL Routing Basics: The GPS of Your Web App 🗺️
The Big Picture: What is URL Routing?
Imagine your website is a giant post office. Every day, thousands of letters (requests) arrive. Each letter has an address written on it (the URL). The postal workers (Flask’s routing system) need to look at each address and deliver the letter to the right mailbox (your Python function).
That’s URL routing! It’s the system that reads the address in the browser and decides which part of your code should handle it.
1. Routes and URL Mapping
The Story
Think of routes like doors in a building. Each door has a number (URL), and behind each door is a specific room (Python function).
When someone types www.mysite.com/hello in their browser, Flask looks at /hello and thinks: “Ah! I know which door this is! Let me open it and show what’s inside.”
How It Works
from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def say_hello():
return 'Hello, World!'
Breaking it down:
/hellois the address (URL path)say_hello()is the mailbox (function)- When someone visits
/hello, Flask runssay_hello()
Real World Example
@app.route('/')
def home():
return 'Welcome to Home!'
@app.route('/about')
def about():
return 'About Us Page'
@app.route('/contact')
def contact():
return 'Contact Us Page'
| URL Typed | Function Called | What User Sees |
|---|---|---|
/ |
home() |
Welcome to Home! |
/about |
about() |
About Us Page |
/contact |
contact() |
Contact Us Page |
2. Route Decorators
The Story
A decorator is like a name tag you stick on a function. It tells Flask: “Hey! This function belongs to THIS address!”
The @app.route() is the decorator. The @ symbol is Python’s way of saying “attach this label.”
Simple Example
@app.route('/pizza')
def pizza_page():
return 'Pizza Menu Here!'
Think of it like this:
- 📝 The label:
@app.route('/pizza') - 📦 The box it’s stuck on:
pizza_page()
Multiple Decorators = Multiple Doors, Same Room!
One function can have many addresses:
@app.route('/')
@app.route('/home')
@app.route('/index')
def homepage():
return 'You are home!'
Now typing /, /home, OR /index all lead to the same place!
3. Static Routes
The Story
Static routes are like addresses carved in stone. They never change. If you type /about, you always get the About page. Period.
Examples
@app.route('/menu')
def menu():
return 'Our Menu'
@app.route('/gallery')
def gallery():
return 'Photo Gallery'
@app.route('/faq')
def faq():
return 'Frequently Asked Questions'
Why “static”?
- The URL is fixed:
/menuis always/menu - Everyone who visits
/menusees the same thing
graph TD A[User types /menu] --> B[Flask checks routes] B --> C[Matches /menu route] C --> D[Runs menu function] D --> E[Shows 'Our Menu']
4. Dynamic Routes with Variables
The Story
Now things get exciting! What if you want to greet users by their name?
You could make a route for every name:
/hello/alice→ one function/hello/bob→ another function/hello/charlie→ another…
That’s crazy! Instead, we use dynamic routes.
A dynamic route is like a form letter with a blank space: “Hello, ____!” Flask fills in the blank.
How to Create Dynamic Routes
Use <variable_name> in the URL:
@app.route('/hello/<name>')
def greet(name):
return f'Hello, {name}!'
What happens:
| URL Typed | Variable name |
Output |
|---|---|---|
/hello/Alice |
Alice | Hello, Alice! |
/hello/Bob |
Bob | Hello, Bob! |
/hello/Pizza |
Pizza | Hello, Pizza! |
Another Example: User Profiles
@app.route('/user/<username>')
def profile(username):
return f'Profile: {username}'
Visiting /user/superhero123 shows: Profile: superhero123
graph TD A[/user/superhero123] --> B[Flask sees /user/...] B --> C[Captures 'superhero123'] C --> D[Passes to profile] D --> E[Profile: superhero123]
5. URL Variable Types
The Story
By default, everything in a URL is a string (text). But what if you need a number?
Imagine a shop with products. Each product has an ID number:
- Product #1, Product #2, Product #3…
You want /product/1 to show Product 1.
The Problem
@app.route('/product/<product_id>')
def product(product_id):
# product_id is a STRING "1", not number 1
next_product = product_id + 1 # ERROR!
This breaks because "1" + 1 doesn’t work in Python!
The Solution: Type Hints
@app.route('/product/<int:product_id>')
def product(product_id):
# Now product_id IS a number!
next_product = product_id + 1 # Works!
return f'Product #{product_id}'
Available Types
| Type | What It Accepts | Example |
|---|---|---|
string |
Text (default) | /user/alice |
int |
Whole numbers | /page/42 |
float |
Decimal numbers | /price/9.99 |
path |
Text with slashes | /file/docs/guide.pdf |
6. URL Converters
The Story
URL converters are the gatekeepers. They check if the URL value is the right type and convert it automatically.
int Converter
Only accepts whole numbers:
@app.route('/page/<int:page_num>')
def show_page(page_num):
return f'Page {page_num}'
/page/5→ Works! Shows “Page 5”/page/abc→ 404 Error! Not a number!
float Converter
Accepts decimal numbers:
@app.route('/temp/<float:celsius>')
def convert_temp(celsius):
fahrenheit = (celsius * 9/5) + 32
return f'{celsius}C = {fahrenheit}F'
/temp/25.5→ Works! Shows “25.5C = 77.9F”
path Converter
Accepts text WITH slashes:
@app.route('/download/<path:filepath>')
def download(filepath):
return f'Downloading: {filepath}'
/download/docs/report.pdf→filepath = "docs/report.pdf"
Without path:, Flask would stop at the first /.
Comparison Table
# Without converter (string default)
@app.route('/item/<item>') # /item/abc → item = "abc"
# With int converter
@app.route('/item/<int:id>') # /item/123 → id = 123 (number)
# With float converter
@app.route('/price/<float:p>') # /price/9.99 → p = 9.99
# With path converter
@app.route('/file/<path:f>') # /file/a/b/c → f = "a/b/c"
Putting It All Together
Here’s a mini website using everything we learned:
from flask import Flask
app = Flask(__name__)
# Static route - homepage
@app.route('/')
def home():
return 'Welcome to BookStore!'
# Static route - about page
@app.route('/about')
def about():
return 'About Our Store'
# Dynamic route - book by title
@app.route('/book/<title>')
def book(title):
return f'Book: {title}'
# Dynamic with int - book by ID
@app.route('/book/id/<int:book_id>')
def book_by_id(book_id):
return f'Book #{book_id}'
# Dynamic with float - price filter
@app.route('/under/<float:max_price>')
def under_price(max_price):
return f'Books under ${max_price}'
# Dynamic with path - file download
@app.route('/ebook/<path:filename>')
def download_ebook(filename):
return f'Download: {filename}'
if __name__ == '__main__':
app.run(debug=True)
graph TD A[User Request] --> B{URL?} B -->|/| C[Home Page] B -->|/about| D[About Page] B -->|/book/python| E[Book: python] B -->|/book/id/42| F[Book #42] B -->|/under/19.99| G[Under $19.99] B -->|/ebook/ch1/intro.pdf| H[Download ch1/intro.pdf]
Quick Reference
| Concept | Example | What It Does |
|---|---|---|
| Static Route | @app.route('/about') |
Fixed URL, never changes |
| Dynamic Route | @app.route('/user/<name>') |
Captures variable from URL |
| int Converter | <int:id> |
Only numbers, converted to integer |
| float Converter | <float:price> |
Decimal numbers |
| path Converter | <path:file> |
Text including slashes |
| Multiple Routes | Stack @app.route() |
Same function, multiple URLs |
You Did It! 🎉
You now understand Flask URL routing:
- âś… Routes map URLs to functions - like addresses to mailboxes
- âś… Decorators label functions -
@app.route()sticks the address on - âś… Static routes are fixed - always the same URL
- âś… Dynamic routes capture variables -
<name>grabs values - âś… Converters validate types -
int:,float:,path:
Now go build something awesome with Flask! 🚀