Skip to content
intermediate Phase 9 · Python APIs & Web

Flask Web Framework

Build web apps and APIs with Flask — routing, templates, and blueprints.

1h 30m
0 problems
Topic Progress 0%

Flask Basics

Hello World

from flask import Flask

app = Flask(__name__)

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

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

Route Decorators

@app.route('/')
def index():
    return 'Home Page'

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

# Variable rules
@app.route('/user/<username>')
def user_profile(username):
    return f'Profile: {username}'

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

# HTTP methods
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return 'Logged in!'
    return 'Login form'

Request Object

from flask import request

@app.route('/search')
def search():
    query = request.args.get('q', '')
    page = request.args.get('page', 1, type=int)
    return f'Search: {query}, Page: {page}'

@app.route('/data', methods=['POST'])
def receive_data():
    data = request.get_json()
    return {'received': data}

Responses

from flask import jsonify, make_response

# Return string
return 'Hello'

# Return JSON
return jsonify({'message': 'Hello'})

# Return with status code
return jsonify({'error': 'Not found'}), 404

# Return with headers
response = make_response(jsonify({'data': 'value'}))
response.headers['X-Custom'] = 'header'
return response

Templates & Forms

Jinja2 Templates

from flask import render_template

@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name, age=30)

Template Syntax

<!-- templates/user.html -->
<!DOCTYPE html>
<html>
<head><title>{{ name }}</title></head>
<body>
    <h1>Hello, {{ name }}!</h1>
    <p>Age: {{ age }}</p>
    
    {% if age >= 18 %}
        <p>Adult</p>
    {% else %}
        <p>Minor</p>
    {% endif %}
    
    <ul>
    {% for item in items %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
</body>
</html>

Template Inheritance

<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My App{% endblock %}</title>
</head>
<body>
    <nav>Navigation</nav>
    {% block content %}{% endblock %}
    <footer>Footer</footer>
</body>
</html>

<!-- templates/user.html -->
{% extends 'base.html' %}

{% block title %}{{ name }}{% endblock %}

{% block content %}
    <h1>Hello, {{ name }}!</h1>
{% endblock %}

Forms

from flask import request, redirect, url_for, flash

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        if authenticate(username, password):
            flash('Logged in successfully!')
            return redirect(url_for('index'))
        else:
            flash('Invalid credentials')
    
    return render_template('login.html')

WTForms

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email

class LoginForm(FlaskForm):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # Process form
        return redirect(url_for('index'))
    return render_template('login.html', form=form)

Blueprints & Organization

What are Blueprints?

Blueprints organize Flask applications into modular components.

# auth/routes.py
from flask import Blueprint, request, jsonify

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    # ... authentication logic
    return jsonify({'token': 'abc123'})

@auth_bp.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    # ... registration logic
    return jsonify({'message': 'User created'}), 201

Registering Blueprints

# app.py
from flask import Flask
from auth.routes import auth_bp
from users.routes import users_bp

def create_app():
    app = Flask(__name__)
    
    # Register blueprints
    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(users_bp, url_prefix='/users')
    
    return app

app = create_app()

Project Structure

myapp/
├── app.py
├── auth/
│   ├── __init__.py
│   ├── routes.py
│   └── forms.py
├── users/
│   ├── __init__.py
│   ├── routes.py
│   └── models.py
├── templates/
│   ├── base.html
│   └── auth/
│       └── login.html
└── static/
    ├── css/
    └── js/

Error Handling

@app.errorhandler(404)
def not_found(error):
    return jsonify({'error': 'Not found'}), 404

@app.errorhandler(500)
def internal_error(error):
    return jsonify({'error': 'Internal server error'}), 500

# Custom exceptions
class APIError(Exception):
    def __init__(self, message, status_code=400):
        self.message = message
        self.status_code = status_code

@app.errorhandler(APIError)
def handle_api_error(error):
    return jsonify({'error': error.message}), error.status_code

Configuration

import os

class Config:
    SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret')
    DEBUG = False
    DATABASE_URI = os.getenv('DATABASE_URI')

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    DEBUG = False

config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

app = Flask(__name__)
app.config.from_object(config[os.getenv('FLASK_ENV', 'default')])