Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

Β© 2026 rakrisi Daily

Routes and Views - URL Routing in Flask

Routes and Views: URL Routing in Flask

Welcome to Routes and Views! Think of routes as street addresses in a city - they tell Flask exactly where to send visitors when they type URLs into their browsers.

What are Routes?

Routes are the connection points between URLs and Python functions. When someone visits a URL, Flask matches it to a route and runs the corresponding function.

Basic Routing

from flask import Flask

app = Flask(__name__)

# Simple routes
@app.route('/')
def home():
    return "Welcome home!"

@app.route('/about')
def about():
    return "About us"

@app.route('/contact')
def contact():
    return "Contact us"

if __name__ == '__main__':
    app.run(debug=True)

Route Variables

Routes can capture values from URLs:

from flask import Flask

app = Flask(__name__)

# String variables (default)
@app.route('/user/<name>')
def greet_user(name):
    return f"Hello, {name}!"

# Integer variables
@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f"Showing post #{post_id}"

# Float variables
@app.route('/price/<float:amount>')
def show_price(amount):
    return f"Price: ${amount:.2f}"

# UUID variables
@app.route('/item/<uuid:item_id>')
def show_item(item_id):
    return f"Item ID: {item_id}"

# Path variables (includes slashes)
@app.route('/files/<path:file_path>')
def show_file(file_path):
    return f"File path: {file_path}"

if __name__ == '__main__':
    app.run(debug=True)

Route converters:

  • string - Text (default, no slashes)
  • int - Integers
  • float - Floating point numbers
  • path - Text including slashes
  • uuid - UUID strings

HTTP Methods

Different HTTP methods for different operations:

from flask import Flask, request

app = Flask(__name__)

# Default is GET
@app.route('/get-only')
def get_only():
    return "This accepts GET requests"

# Multiple methods
@app.route('/data', methods=['GET', 'POST'])
def handle_data():
    if request.method == 'GET':
        return "Getting data"
    elif request.method == 'POST':
        return "Posting data"

# All methods
@app.route('/everything', methods=['GET', 'POST', 'PUT', 'DELETE'])
def handle_everything():
    return f"Method: {request.method}"

# RESTful routes
@app.route('/users', methods=['GET'])
def list_users():
    return "List all users"

@app.route('/users', methods=['POST'])
def create_user():
    return "Create new user"

@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    return f"Get user {user_id}"

@app.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    return f"Update user {user_id}"

@app.route('/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
    return f"Delete user {user_id}"

if __name__ == '__main__':
    app.run(debug=True)

Request Object

Access request data with the request object:

from flask import Flask, request

app = Flask(__name__)

@app.route('/info')
def request_info():
    return f"""
    Method: {request.method}
    URL: {request.url}
    Headers: {dict(request.headers)}
    Args: {dict(request.args)}
    Form: {dict(request.form)}
    JSON: {request.get_json(silent=True)}
    """

@app.route('/search')
def search():
    # GET parameters
    query = request.args.get('q', '')
    limit = request.args.get('limit', '10')
    return f"Searching for '{query}' with limit {limit}"

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return """
        <form method="POST">
            Username: <input name="username"><br>
            Password: <input name="password" type="password"><br>
            <input type="submit" value="Login">
        </form>
        """
    else:
        username = request.form.get('username')
        password = request.form.get('password')
        return f"Login attempt: {username}"

@app.route('/api/data', methods=['POST'])
def api_data():
    if request.is_json:
        data = request.get_json()
        return f"Received JSON: {data}"
    else:
        return "Expected JSON data", 400

if __name__ == '__main__':
    app.run(debug=True)

URL Building

Generate URLs programmatically:

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def home():
    return "Home page"

@app.route('/user/<name>')
def user_profile(name):
    return f"Profile for {name}"

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

@app.route('/links')
def show_links():
    home_url = url_for('home')
    user_url = url_for('user_profile', name='alice')
    post_url = url_for('show_post', post_id=123)

    return f"""
    <h1>Useful Links</h1>
    <ul>
        <li><a href="{home_url}">Home</a></li>
        <li><a href="{user_url}">Alice's Profile</a></li>
        <li><a href="{post_url}">Post #123</a></li>
    </ul>
    """

if __name__ == '__main__':
    app.run(debug=True)

Route Decorators

Create reusable route decorators:

from flask import Flask, request, g
from functools import wraps

app = Flask(__name__)

# Authentication decorator
def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_id' not in request.cookies:
            return "Please log in first", 401
        return f(*args, **kwargs)
    return decorated_function

# Logging decorator
def log_request(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        print(f"Request to {request.path} from {request.remote_addr}")
        return f(*args, **kwargs)
    return decorated_function

# API response decorator
def json_response(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        result = f(*args, **kwargs)
        if isinstance(result, dict):
            from flask import jsonify
            return jsonify(result)
        return result
    return decorated_function

@app.route('/')
@log_request
def home():
    return "Welcome!"

@app.route('/profile')
@login_required
@log_request
def profile():
    return "Your profile"

@app.route('/api/users')
@json_response
def api_users():
    return {
        'users': [
            {'id': 1, 'name': 'Alice'},
            {'id': 2, 'name': 'Bob'}
        ]
    }

if __name__ == '__main__':
    app.run(debug=True)

Advanced Routing

Route Groups and Blueprints

from flask import Flask, Blueprint

app = Flask(__name__)

# Create blueprint for blog
blog_bp = Blueprint('blog', __name__, url_prefix='/blog')

@blog_bp.route('/')
def blog_home():
    return "Blog home"

@blog_bp.route('/post/<int:post_id>')
def blog_post(post_id):
    return f"Blog post {post_id}"

# Create blueprint for API
api_bp = Blueprint('api', __name__, url_prefix='/api/v1')

@api_bp.route('/users')
def api_users():
    return "API users"

@api_bp.route('/posts')
def api_posts():
    return "API posts"

# Register blueprints
app.register_blueprint(blog_bp)
app.register_blueprint(api_bp)

if __name__ == '__main__':
    app.run(debug=True)

Custom Route Converters

from flask import Flask
from werkzeug.routing import BaseConverter

class ListConverter(BaseConverter):
    def to_python(self, value):
        return value.split(',')

    def to_url(self, values):
        return ','.join(str(v) for v in values)

app = Blueprint('api', __name__)
app.url_map.converters['list'] = ListConverter

@app.route('/users/<list:user_ids>')
def get_users(user_ids):
    return f"Users: {user_ids}"

# Usage: /users/1,2,3,4

Route Redirects

from flask import Flask, redirect, url_for, abort

app = Flask(__name__)

@app.route('/')
def home():
    return "Home page"

@app.route('/old-url')
def old_url():
    return redirect(url_for('home'))

@app.route('/user/<int:user_id>')
def user_profile(user_id):
    if user_id > 1000:
        abort(404)  # User not found
    return f"User {user_id}"

@app.route('/admin')
def admin():
    # Check if user is admin
    is_admin = False  # In real app, check session/cookies
    if not is_admin:
        return redirect(url_for('home'))
    return "Admin panel"

if __name__ == '__main__':
    app.run(debug=True)

Practical Examples

Example 1: Blog Application

from flask import Flask, request, redirect, url_for

app = Flask(__name__)

# Mock database
posts = [
    {'id': 1, 'title': 'First Post', 'content': 'Hello world!'},
    {'id': 2, 'title': 'Second Post', 'content': 'Flask is awesome!'},
]

@app.route('/')
def home():
    html = "<h1>My Blog</h1><ul>"
    for post in posts:
        html += f"<li><a href='/post/{post['id']}'>{post['title']}</a></li>"
    html += "</ul><a href='/new'>Create new post</a>"
    return html

@app.route('/post/<int:post_id>')
def show_post(post_id):
    post = next((p for p in posts if p['id'] == post_id), None)
    if not post:
        return "Post not found", 404

    return f"""
    <h1>{post['title']}</h1>
    <p>{post['content']}</p>
    <a href='/'>Back to home</a>
    """

@app.route('/new', methods=['GET', 'POST'])
def new_post():
    if request.method == 'GET':
        return """
        <h1>Create New Post</h1>
        <form method="POST">
            Title: <input name="title" required><br>
            Content: <textarea name="content" required></textarea><br>
            <input type="submit" value="Create Post">
        </form>
        """
    else:
        title = request.form.get('title')
        content = request.form.get('content')

        new_post = {
            'id': len(posts) + 1,
            'title': title,
            'content': content
        }
        posts.append(new_post)

        return redirect(url_for('show_post', post_id=new_post['id']))

if __name__ == '__main__':
    app.run(debug=True)

Example 2: REST API

from flask import Flask, jsonify, request, abort

app = Flask(__name__)

# Mock database
todos = [
    {'id': 1, 'title': 'Learn Flask', 'completed': False},
    {'id': 2, 'title': 'Build API', 'completed': True},
]

@app.route('/api/todos', methods=['GET'])
def get_todos():
    return jsonify(todos)

@app.route('/api/todos/<int:todo_id>', methods=['GET'])
def get_todo(todo_id):
    todo = next((t for t in todos if t['id'] == todo_id), None)
    if not todo:
        abort(404)
    return jsonify(todo)

@app.route('/api/todos', methods=['POST'])
def create_todo():
    if not request.is_json:
        return jsonify({'error': 'Request must be JSON'}), 400

    data = request.get_json()
    if 'title' not in data:
        return jsonify({'error': 'Title is required'}), 400

    new_todo = {
        'id': len(todos) + 1,
        'title': data['title'],
        'completed': data.get('completed', False)
    }
    todos.append(new_todo)

    return jsonify(new_todo), 201

@app.route('/api/todos/<int:todo_id>', methods=['PUT'])
def update_todo(todo_id):
    todo = next((t for t in todos if t['id'] == todo_id), None)
    if not todo:
        abort(404)

    if not request.is_json:
        return jsonify({'error': 'Request must be JSON'}), 400

    data = request.get_json()
    todo.update(data)
    return jsonify(todo)

@app.route('/api/todos/<int:todo_id>', methods=['DELETE'])
def delete_todo(todo_id):
    global todos
    todos = [t for t in todos if t['id'] != todo_id]
    return '', 204

if __name__ == '__main__':
    app.run(debug=True)

Example 3: E-commerce Routes

from flask import Flask, request, session, redirect, url_for

app = Flask(__name__)
app.secret_key = 'your-secret-key'

# Mock data
products = [
    {'id': 1, 'name': 'Laptop', 'price': 999.99},
    {'id': 2, 'name': 'Mouse', 'price': 29.99},
]

@app.route('/')
def home():
    return "Welcome to our store!"

@app.route('/products')
def list_products():
    html = "<h1>Our Products</h1><ul>"
    for product in products:
        html += f"""
        <li>
            {product['name']} - ${product['price']}
            <a href="/product/{product['id']}">View</a>
            <a href="/cart/add/{product['id']}">Add to Cart</a>
        </li>
        """
    html += "</ul><a href='/cart'>View Cart</a>"
    return html

@app.route('/product/<int:product_id>')
def show_product(product_id):
    product = next((p for p in products if p['id'] == product_id), None)
    if not product:
        return "Product not found", 404

    return f"""
    <h1>{product['name']}</h1>
    <p>Price: ${product['price']}</p>
    <a href="/cart/add/{product['id']}">Add to Cart</a>
    <a href="/products">Back to products</a>
    """

@app.route('/cart')
def view_cart():
    cart = session.get('cart', [])
    if not cart:
        return "Your cart is empty <a href='/products'>Shop now</a>"

    total = 0
    html = "<h1>Your Cart</h1><ul>"
    for item in cart:
        product = next((p for p in products if p['id'] == item['id']), None)
        if product:
            html += f"<li>{product['name']} - ${product['price']}</li>"
            total += product['price']
    html += f"</ul><p>Total: ${total:.2f}</p>"
    return html

@app.route('/cart/add/<int:product_id>')
def add_to_cart(product_id):
    product = next((p for p in products if p['id'] == product_id), None)
    if not product:
        return "Product not found", 404

    cart = session.get('cart', [])
    cart.append({'id': product_id})
    session['cart'] = cart

    return redirect(url_for('view_cart'))

if __name__ == '__main__':
    app.run(debug=True)

Best Practices

1. Use Descriptive Route Names

# Good
@app.route('/users/<int:user_id>/posts/<int:post_id>')
def show_user_post(user_id, post_id):
    pass

# Bad
@app.route('/u/<uid>/p/<pid>')
def sup(uid, pid):
    pass

2. Validate Route Parameters

@app.route('/user/<int:user_id>')
def show_user(user_id):
    if user_id <= 0:
        abort(400)  # Bad request
    # ... rest of function

3. Use URL Building

# Good
url_for('show_user', user_id=123)

# Bad
'/user/123'

4. Handle Errors Properly

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

@app.errorhandler(500)
def internal_error(error):
    return "Internal server error", 500

5. Use Blueprints for Organization

# For large apps, use blueprints
user_bp = Blueprint('users', __name__, url_prefix='/users')
app.register_blueprint(user_bp)

Practice Exercises

Exercise 1: URL Shortener

Create a URL shortener with routes:

  • POST /shorten - Accept long URL, return short code
  • GET /<short_code> - Redirect to original URL
  • GET /stats/<short_code> - Show click statistics

Exercise 2: Social Media API

Build a social media API with:

  • GET /posts - List all posts
  • POST /posts - Create new post
  • GET /posts/<id> - Get specific post
  • POST /posts/<id>/like - Like a post
  • GET /users/<username> - User profile

Exercise 3: File Manager

Create a file manager with:

  • GET /files - List files in directory
  • GET /files/<path> - Download file
  • POST /files - Upload file
  • DELETE /files/<path> - Delete file

Exercise 4: Quiz Application

Build a quiz app with:

  • GET /quiz - Start new quiz
  • POST /quiz/<quiz_id>/answer - Submit answer
  • GET /quiz/<quiz_id>/result - Show results
  • GET /leaderboard - Show top scores

Summary

Routes and views are Flask’s URL routing system:

Basic Routes:

@app.route('/')
def home():
    return "Hello!"

@app.route('/user/<name>')
def greet(name):
    return f"Hello, {name}!"

HTTP Methods:

@app.route('/data', methods=['GET', 'POST'])
def handle_data():
    if request.method == 'GET':
        return "Getting data"
    else:
        return "Posting data"

Request Data:

query = request.args.get('q')      # GET parameters
data = request.form.get('field')   # Form data
json_data = request.get_json()     # JSON data

URL Building:

url_for('route_name', param=value)

Key Concepts:

  • Route variables with converters (int, float, path)
  • HTTP methods for different operations
  • Request object for accessing data
  • URL building with url_for()
  • Blueprints for organization

Next: Templates - creating dynamic HTML with Jinja2! 🎨