Flask

Python micro framework - minimal core, flexible architecture, add only what you need

TL;DR

One-liner: Flask is Python’s micro framework - minimal core, add what you need.

Core Strengths:

  • Minimal and flexible - no forced project structure
  • Easy to learn - get running in minutes
  • Extensible - huge ecosystem of extensions
  • Werkzeug + Jinja2 - battle-tested foundations

Core Concepts

Concept 1: Routes = Decorators

Define routes with decorators:

from flask import Flask
app = Flask(__name__)

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

@app.route('/users/<int:user_id>')
def get_user(user_id):
    return f'User {user_id}'

Concept 2: Request Context

Access request data through the request object:

from flask import request

@app.route('/search')
def search():
    query = request.args.get('q')        # Query params
    page = request.args.get('page', 1)   # With default
    return f'Searching: {query}'

@app.route('/users', methods=['POST'])
def create_user():
    data = request.json                   # JSON body
    return {'created': data}

Concept 3: Extensions

Flask is intentionally minimal. Add features with extensions:

# Database
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)

# Authentication
from flask_login import LoginManager
login = LoginManager(app)

# REST APIs
from flask_restful import Api
api = Api(app)

Quick Start

Install

pip install flask

Create app.py

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def hello():
    return jsonify({'message': 'Hello Flask!'})

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

Run

flask run --debug
# Open http://localhost:5000

Gotchas

Debug mode is opt-in

# Development - enables auto-reload and debugger
flask run --debug

# Or in code (not for production!)
app.run(debug=True)

# Production - never use debug=True
gunicorn app:app

Methods must be specified

# ❌ POST won't work
@app.route('/users')
def users():
    return 'Users'

# ✅ Explicitly allow POST
@app.route('/users', methods=['GET', 'POST'])
def users():
    if request.method == 'POST':
        return 'Created', 201
    return 'Users'

Application context required

# ❌ Error outside request
from flask import current_app
print(current_app.config)  # RuntimeError!

# ✅ Push context manually
with app.app_context():
    print(current_app.config)

Blueprints for larger apps

# users.py
from flask import Blueprint, jsonify

users_bp = Blueprint('users', __name__)

@users_bp.route('/')
def list_users():
    return jsonify([])

# app.py
from users import users_bp
app.register_blueprint(users_bp, url_prefix='/users')

When to Use

Best for:

  • Small to medium APIs
  • Prototypes and MVPs
  • Teams wanting full control
  • Microservices

Not ideal for:

  • Large apps needing structure (use Django)
  • Async-heavy apps (use FastAPI)
  • Production APIs needing auto-docs (use FastAPI)

Comparison:

FeatureFlaskDjangoFastAPI
SizeMicroFullMicro
Learning curveEasyMediumEasy
Auto docsNoNoYes
AsyncLimitedLimitedNative

Next Steps

Cheatsheet

PatternCode
Route@app.route('/path')
Methods@app.route('/', methods=['GET', 'POST'])
URL param@app.route('/<int:id>')
Query paramrequest.args.get('q')
JSON bodyrequest.json
JSON responsejsonify({'key': 'value'})
Status codereturn data, 201
Redirectredirect(url_for('index'))
Templaterender_template('index.html', name=name)
BlueprintBlueprint('name', __name__)