Module 10.1

Flask Basics

Flask is a lightweight web framework - simple but powerful. Build web applications with minimal code while keeping full control over your application architecture. Learn routing, request handling, and the fundamentals of web development with Python.

45 min
Intermediate
Hands-on
What You'll Learn
  • Create a Flask application from scratch
  • Define routes with the @app.route decorator
  • Handle dynamic URLs with parameters
  • Work with GET and POST methods
  • Understand the request-response cycle
Contents
01

Introduction to Flask

Flask is a micro web framework for Python that provides the essentials for building web applications without imposing rigid patterns. Its simplicity makes it perfect for beginners, while its extensibility satisfies the needs of complex applications.

Key Concept

What is Flask?

Flask is a lightweight WSGI (Web Server Gateway Interface) web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. Flask provides the core tools - routing, request handling, and templating - while letting you choose additional components as needed.

Why it matters: Flask's "micro" philosophy means less boilerplate code, faster development cycles, and easier debugging. You add only what you need, keeping your application lean and maintainable.

Request-Response Cycle
Client
Browser
Request
Flask
Server
Route
View
Function
Return
Response
HTML/JSON

The diagram above shows how Flask handles web requests: the client sends a request, Flask matches it to a route, executes the view function, and returns a response.

Why Choose Flask?

Lightweight

Minimal dependencies and small footprint. Start with just a few lines of code.

Flexible

No forced project structure. Choose your own database, template engine, and tools.

Well Documented

Excellent documentation and large community. Easy to find help and resources.

Installing Flask

Flask can be installed using pip. It is recommended to use a virtual environment to keep your project dependencies isolated.

# Create a virtual environment (recommended)
# python -m venv venv
# source venv/bin/activate  (Linux/Mac)
# venv\Scripts\activate     (Windows)

# Install Flask
# pip install flask

# Verify installation
import flask
print(f"Flask version: {flask.__version__}")

Always use a virtual environment for Flask projects. This keeps dependencies isolated and makes deployment easier.

02

Your First Flask App

Let's create a minimal Flask application to understand the basic structure. With just five lines of code, you can have a working web server.

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, World!'

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

This minimal application creates a Flask instance, defines a single route, and runs the development server. Save this as app.py and run it with python app.py.

Understanding the Code

Line Purpose Explanation
Flask(__name__) Create app instance Creates the Flask application object. __name__ helps Flask locate resources.
@app.route('/') Route decorator Maps the URL path "/" to the function below it.
def hello() View function Returns the response when this route is accessed.
app.run(debug=True) Start server Runs the development server with auto-reload enabled.
Route Decorator Anatomy
@app.route('/users/')
def show_user(user_id):
    return f'User ID: {user_id}'
@app.route The decorator that registers URLs
'/users/' Static URL prefix
<int:user_id> Dynamic parameter with type
def function() View function that handles requests
Pro Tip: Always use debug=True during development. It enables auto-reload on code changes and provides helpful error pages. Never use debug mode in production!
03

Routing Fundamentals

Routes define the URLs your application responds to. The @app.route() decorator connects URL patterns to Python functions, making URL management intuitive and declarative.

Basic Routes

Each route decorator maps a URL pattern to a view function. When a user visits that URL, Flask calls the associated function and returns its output as the HTTP response.

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Welcome to the Home Page!'

@app.route('/about')
def about():
    return 'About Us Page'

@app.route('/contact')
def contact():
    return 'Contact Us Page'

Each @app.route() decorator creates a unique endpoint. The function name becomes the endpoint name, used for URL generation with url_for().

Multiple Routes for One Function

A single view function can handle multiple URL patterns by stacking decorators.

@app.route('/')
@app.route('/home')
@app.route('/index')
def homepage():
    return 'This is the homepage!'

# All three URLs point to the same function:
# / , /home , /index

Stacking multiple route decorators is useful for supporting legacy URLs or providing user-friendly aliases.

Trailing Slashes

Flask has specific behavior for trailing slashes. Understanding this prevents 404 errors.

# With trailing slash - works with or without slash
@app.route('/projects/')
def projects():
    return 'Projects Page'
# /projects and /projects/ both work (redirects to /projects/)

# Without trailing slash - strict matching
@app.route('/about')
def about():
    return 'About Page'
# /about works, but /about/ returns 404
Consistency Tip: Choose a convention (with or without trailing slashes) and stick to it throughout your application for predictable behavior.
04

Dynamic Routes

Dynamic routes allow you to capture variable parts of the URL and pass them as arguments to your view function. This is essential for building RESTful APIs and user-specific pages.

URL Parameters

Use angle brackets <variable_name> to capture URL segments. The captured value is passed to the view function as an argument.

@app.route('/user/')
def show_user(username):
    return f'Hello, {username}!'

# /user/john -> 'Hello, john!'
# /user/jane -> 'Hello, jane!'

@app.route('/post/')
def show_post(post_id):
    return f'Showing post #{post_id}'

# /post/42 -> 'Showing post #42'

Dynamic segments are captured and passed as function arguments. The variable name in the route must match the function parameter name.

URL Converters

Flask provides type converters to validate and convert URL parameters automatically.

Converter Description Example
string Default, accepts any text without slashes <username>
int Accepts positive integers <int:user_id>
float Accepts positive floating point values <float:price>
path Like string but accepts slashes <path:filepath>
uuid Accepts UUID strings <uuid:item_id>
@app.route('/product/')
def product(product_id):
    # product_id is already an integer
    return f'Product: {product_id}, Type: {type(product_id)}'

@app.route('/files/')
def serve_file(filepath):
    # filepath can contain slashes: 'docs/images/logo.png'
    return f'Serving: {filepath}'

Type converters ensure URLs are valid and convert values to the appropriate Python type. Invalid URLs (e.g., /product/abc for int) return 404.

Multiple Parameters

@app.route('/user//post/')
def user_post(username, post_id):
    return f'Post #{post_id} by {username}'

# /user/john/post/5 -> 'Post #5 by john'
05

HTTP Methods

HTTP methods define the action to perform on a resource. Flask routes respond to GET requests by default, but you can specify other methods to handle form submissions and API operations.

GET Request
  • Retrieves data from the server
  • Parameters visible in URL
  • Can be bookmarked
  • Cached by browsers
  • Safe and idempotent
POST Request
  • Sends data to the server
  • Parameters in request body
  • Cannot be bookmarked
  • Not cached
  • Used for form submissions

Specifying HTTP Methods

from flask import Flask, request

app = Flask(__name__)

# Handle both GET and POST
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # Process form submission
        username = request.form.get('username')
        return f'Logging in as {username}'
    # Show login form
    return 'Login Form (GET request)'

The methods parameter accepts a list of HTTP methods. Use request.method to determine which method was used.

RESTful Route Example

from flask import Flask, request, jsonify

app = Flask(__name__)
users = {}

@app.route('/api/users', methods=['GET'])
def get_users():
    return jsonify(list(users.values()))

@app.route('/api/users', methods=['POST'])
def create_user():
    data = request.get_json()
    user_id = len(users) + 1
    users[user_id] = {'id': user_id, 'name': data['name']}
    return jsonify(users[user_id]), 201

RESTful APIs typically use GET for reading, POST for creating, PUT for updating, and DELETE for removing resources.

06

Request-Response Cycle

Understanding the request object and how to build responses is fundamental to Flask development. Flask provides powerful objects for handling incoming data and crafting outgoing responses.

The Request Object

The request object contains all the data sent by the client, including form data, query parameters, JSON payloads, headers, and files.

from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def search():
    # Query parameters: /search?q=flask&page=1
    query = request.args.get('q', '')
    page = request.args.get('page', 1, type=int)
    return f'Searching for: {query}, Page: {page}'

@app.route('/submit', methods=['POST'])
def submit():
    name = request.form.get('name')
    email = request.form.get('email')
    return f'Received: {name} - {email}'

Use request.args for query parameters (GET) and request.form for form data (POST). The get() method provides defaults for missing values.

Common Request Attributes

Attribute Description Example Use
request.args URL query parameters request.args.get('page')
request.form Form data (POST) request.form.get('email')
request.json JSON payload request.json['name']
request.method HTTP method used if request.method == 'POST'
request.headers Request headers request.headers.get('Authorization')

Building Responses

from flask import Flask, jsonify, make_response, redirect, url_for

app = Flask(__name__)

@app.route('/api/data')
def api_data():
    return jsonify({'status': 'success', 'data': [1, 2, 3]})

@app.route('/custom')
def custom_response():
    response = make_response('Custom Response', 201)
    response.headers['X-Custom-Header'] = 'CustomValue'
    return response

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

Flask provides helpers for common response types: jsonify() for JSON, make_response() for custom responses, and redirect() for redirections.

07

Practice Exercises

Apply what you have learned with these hands-on coding exercises. Start with the basics and work your way up to more complex challenges.

Flask Basics Practice

Task: Create a Flask application with a single route "/" that returns "Welcome to Flask!"

Show Solution
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Welcome to Flask!'

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

Task: Add routes for /about, /contact, and /services that return appropriate messages.

Show Solution
@app.route('/about')
def about():
    return 'About Us - We are a Flask company!'

@app.route('/contact')
def contact():
    return 'Contact us at: hello@flask.com'

@app.route('/services')
def services():
    return 'Our Services: Web Development, APIs, More'

Task: Create a route /greet/<name> that returns a personalized greeting like "Hello, John!"

Show Solution
@app.route('/greet/')
def greet(name):
    return f'Hello, {name.capitalize()}!'

# Test: /greet/john -> "Hello, John!"

Task: Create a route /add/<int:a>/<int:b> that returns the sum of two numbers.

Show Solution
@app.route('/add//')
def add(a, b):
    result = a + b
    return f'{a} + {b} = {result}'

# Test: /add/5/3 -> "5 + 3 = 8"

Task: Create a /search route that accepts 'q' and 'limit' query parameters and returns them.

Show Solution
from flask import request

@app.route('/search')
def search():
    query = request.args.get('q', 'No query')
    limit = request.args.get('limit', 10, type=int)
    return f'Searching: "{query}" with limit: {limit}'

# Test: /search?q=flask&limit=5

Task: Create a /login route that shows "Login Form" on GET and processes credentials on POST.

Show Solution
from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username and password:
            return f'Welcome, {username}!'
        return 'Missing credentials', 400
    return 'Login Form - Please POST credentials'

Task: Create a /api/user/<int:id> route that returns user data as JSON with name and email.

Show Solution
from flask import jsonify

users_db = {
    1: {'name': 'Alice', 'email': 'alice@example.com'},
    2: {'name': 'Bob', 'email': 'bob@example.com'}
}

@app.route('/api/user/')
def get_user(id):
    user = users_db.get(id)
    if user:
        return jsonify({'id': id, **user})
    return jsonify({'error': 'User not found'}), 404

Task: Create a POST /api/items endpoint that accepts JSON data and adds it to a list.

Show Solution
from flask import request, jsonify

items = []

@app.route('/api/items', methods=['GET', 'POST'])
def handle_items():
    if request.method == 'POST':
        data = request.get_json()
        if not data or 'name' not in data:
            return jsonify({'error': 'Name required'}), 400
        item = {'id': len(items) + 1, 'name': data['name']}
        items.append(item)
        return jsonify(item), 201
    return jsonify(items)

Task: Create an /old-home route that redirects to /home using url_for for dynamic URL generation.

Show Solution
from flask import redirect, url_for

@app.route('/home')
def home():
    return 'Welcome to the new home page!'

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

# Visiting /old-home redirects to /home

Key Takeaways

Lightweight Framework

Flask is a micro framework that gives you the essentials without imposing structure - add only what you need

Declarative Routing

The @app.route decorator maps URL patterns to Python functions in a clean, readable way

Dynamic URLs

Capture URL segments with converters like <int:id> to build flexible, RESTful routes

HTTP Methods

Handle GET for reading, POST for creating - use request.method to differentiate in views

Request Object

Access form data, query params, JSON, and headers through the request object

Response Helpers

Use jsonify() for APIs, make_response() for custom headers, redirect() for navigation

Knowledge Check

Quick Quiz

Test what you've learned about Flask basics

1 What does Flask's @app.route() decorator do?
2 How do you capture a dynamic URL parameter in Flask?
3 What is the purpose of debug=True in app.run()?
4 How do you access form data from a POST request in Flask?
5 What does the jsonify() function do?
6 What is the purpose of url_for() in Flask?
Answer all questions to check your score