Flask Cheat Sheet: A Comprehensive Quick-Reference Guide

Flask Cheat Sheet: A Comprehensive Quick-Reference Guide

Verified Sources
Jun 19, 2026

Flask is a lightweight WSGI micro-framework for Python, designed to make getting started quick and easy, with the ability to scale up to complex applications. It was created by Armin Ronacher and is classified as a micro-framework because it does not require particular tools or libraries — it has no database abstraction layer, form validation, or any other pre-existing third-party library that provides common functions .

Flask's core philosophy is built on two pillars: the Werkzeug WSGI toolkit and the Jinja2 templating engine. Together, they give you URL routing, request/response handling, a development server, and powerful template rendering — all without the overhead of a full-stack framework.

The framework follows the MVC pattern loosely, giving you the flexibility to structure your app as you see fit. Flask's minimalist approach means you only add what you need — Flask-SQLAlchemy for databases, Flask-WTF for forms, Flask-Login for authentication, and so on.

Footnotes

  1. Flask Official Documentation — The primary reference for Flask's API, patterns, and best practices including routing, contexts, and deployment guidelines.

Flask Cheatsheet for Beginners

Application Setup & Configuration

Every Flask application begins by creating an application instance:

1from flask import Flask 2 3app = Flask(__name__) 4 5@app.route('/') 6def home(): 7 return 'Hello, World!' 8 9if __name__ == '__main__': 10 app.run(debug=True, port=5000)

The __name__ argument tells Flask where to look for templates, static files, and other resources. When debug=True, Flask enables the interactive debugger and auto-reloads on code changes — never use this in production .

Configuration MethodSyntaxUse Case
From dictionaryapp.config['DEBUG'] = TrueQuick single-value setting
From objectapp.config.from_object('config.DevConfig')Class-based configs
From fileapp.config.from_pyfile('config.py')File-based configs
From environmentapp.config.from_envvar('APP_SETTINGS')12-factor app pattern
From JSONapp.config.from_json('config.json')JSON-based configs

Key built-in configuration variables:

VariableDefaultDescription
DEBUGFalseEnable debug mode
SECRET_KEYNoneUsed for sessions & CSRF protection
SESSION_COOKIE_SECUREFalseSet secure flag on session cookies
MAX_CONTENT_LENGTHNoneMax request size in bytes
JSON_SORT_KEYSTrueSort JSON response keys

Footnotes

  1. Flask Official Documentation — The primary reference for Flask's API, patterns, and best practices including routing, contexts, and deployment guidelines.

Never Set DEBUG=True in Production

The Flask debugger allows execution of arbitrary Python code in the browser. Exposing DEBUG=True in production is a critical security vulnerability that can lead to remote code execution. Always use environment variables to control this setting.

Routing & URL Dispatching

Routing maps URLs to Python functions. Flask uses the route decorator to connect URL patterns to handler functions.

1# Basic routes 2@app.route('/') 3def index(): 4 return 'Index Page' 5 6@app.route('/hello') 7def hello(): 8 return 'Hello, World' 9 10# Dynamic routes with variable rules 11@app.route('/user/<username>') 12def show_user(username): 13 return f'User: {username}' 14 15@app.route('/post/<int:post_id>') 16def show_post(post_id): 17 return f'Post ID: {post_id}' 18 19@app.route('/path/<path:subpath>') 20def show_subpath(subpath): 21 return f'Subpath: {subpath}'

Variable converters:

ConverterTypeExample
stringAny text (default)<name>
intPositive integers<int:id>
floatPositive floats<float:price>
pathText with slashes<path:filepath>
uuidUUID strings<uuid:task_id>

HTTP method binding:

1@app.route('/api/data', methods=['GET', 'POST']) 2def handle_data(): 3 if request.method == 'POST': 4 return 'Created', 201 5 return 'Data list', 200

url_for() — the proper way to build URLs:

1from flask import url_for 2 3url_for('show_user', username='alice') # /user/alice 4url_for('static', filename='style.css') # /static/style.css

Request-Response Lifecycle in Flask

  1. 1
    Step 1

    The browser or API client sends an HTTP request to the Flask development server. The request includes a method (GET, POST, etc.), URL, headers, and optional body.

  2. 2
    Step 2

    Werkzeug receives the raw HTTP request and wraps it into a WSGI-compatible environ dictionary. This is the interface between the web server and Flask.

  3. 3
    Step 3

    Flask's URL map compares the request path against all registered route rules. If a match is found, the corresponding view function is identified. If no match exists, a 404 error is raised. URL rule precedence follows the most specific match .

    Footnotes

    1. Flask Official Documentation — The primary reference for Flask's API, patterns, and best practices including routing, contexts, and deployment guidelines.

  4. 4
    Step 4

    Any functions registered with @app.before_request run in order. These can perform authentication checks, database setup, or terminate the request early by returning a response.

  5. 5
    Step 5

    The matched view function runs. It has access to the request object with all incoming data. The function processes business logic and returns a response — either a string, a dict (auto-converted to JSON), a tuple, or a Response object.

  6. 6
    Step 6

    Functions registered with @app.after_request run on the response object. They can modify headers, log data, or transform the response. The @app.teardown_request hooks run even if an exception occurred.

  7. 7
    Step 7

    Flask converts the return value to a proper HTTP Response object (if not already one), adds status code and headers, and sends it back through Werkzeug to the client.

The Request Object

Flask's request context provides access to all incoming request data through the global request object:

1from flask import request 2 3# Request method & URL 4request.method # 'GET', 'POST', etc. 5request.url # Full URL 6request.path # '/api/users' 7request.base_url # URL without query string 8request.args # ImmutableMultiDict of query params 9 10# Form & JSON data 11request.form # Form data (POST) 12request.json # Parsed JSON body 13request.data # Raw body bytes 14 15# Headers & cookies 16request.headers # Dict-like headers 17request.cookies # Dict of cookies 18 19# Files 20request.files # MultiDict of uploaded files 21file = request.files['upload'] 22file.save(f'/uploads/{file.filename}')
AttributeTypeDescription
request.argsImmutableMultiDictURL query parameters
request.formImmutableMultiDictForm body data
request.jsondict or NoneParsed JSON payload
request.filesMultiDictUploaded file objects
request.valuesCombinedMultiDictMerged args + form
request.cookiesdictClient cookies
request.headersEnvironHeadersRequest headers
1from flask import make_response, jsonify 2 3# Simple string response 4@app.route('/text') 5def text_response(): 6 return 'Hello World' 7 8# JSON response (Flask auto-converts dicts) 9@app.route('/json') 10def json_response(): 11 return {'name': 'Alice', 'age': 30} 12 13# With status code 14@app.route('/created') 15def created(): 16 return {'id': 1}, 201 17 18# Full control with make_response 19@app.route('/full') 20def full_response(): 21 resp = make_response({'message': 'ok'}) 22 resp.status_code = 200 23 resp.headers['X-Custom'] = 'Value' 24 resp.set_cookie('token', 'abc123', httponly=True) 25 return resp

Templates with Jinja2

Flask uses Jinja2 for rendering HTML. Templates should be stored in a templates/ directory.

1from flask import render_template 2 3@app.route('/profile/<username>') 4def profile(username): 5 return render_template('profile.html', name=username, age=25)

Template syntax cheat sheet:

1<!-- Variable interpolation --> 2<h1>Hello, {{ name }}!</h1> 3 4<!-- Filters --> 5<p>{{ name|capitalize }}</p> 6<p>{{ price|round(2) }}</p> 7<p>{{ content|truncate(100) }}</p> 8<p>{{ html_content|safe }}</p> 9<p>{{ items|length }}</p> 10 11<!-- Conditionals --> 12{% if user.is_authenticated %} 13 <p>Welcome back, {{ user.name }}</p> 14{% elif user.is_guest %} 15 <p>Browse as guest</p> 16{% else %} 17 <p>Please log in</p> 18{% endif %} 19 20<!-- Loops --> 21{% for item in items %} 22 <li>{{ loop.index }}: {{ item }}</li> 23{% endfor %} 24 25<!-- Macro (reusable template function) --> 26{% macro render_button(text, type='primary') %} 27 <button class="btn btn-{{ type }}">{{ text }}</button> 28{% endmacro %} 29 30{{ render_button('Submit') }} 31{{ render_button('Delete', 'danger') }}

Template inheritance:

1<!-- base.html --> 2<!DOCTYPE html> 3<html> 4<head> 5 <title>{% block title %}Default Title{% endblock %}</title> 6 {% block head %}{% endblock %} 7</head> 8<body> 9 {% block content %}{% endblock %} 10 {% block scripts %}{% endblock %} 11</body> 12</html> 13 14<!-- child.html --> 15{% extends "base.html" %} 16{% block title %}Child Page{% endblock %} 17{% block content %} 18 <h1>Child Content Here</h1> 19{% endblock %}
Jinja2 FeatureSyntaxPurpose
Variable{{ var }}Render value
Tag{% tag %}Logic/control
Comment{# comment #}Template comment (not in output)
Extends{% extends "base.html" %}Inherit parent template
Block{% block name %}...{% endblock %}Define overridable sections
Include{% include "nav.html" %}Insert another template
Macro{% macro name() %}...{% endmacro %}Reusable template function
Set{% set x = 5 %}Assign template variable

Use url_for() Instead of Hardcoded URLs

Always use url_for('endpoint_name', arg=val) in templates to generate URLs. If you later change a route's URL pattern, url_for() automatically updates — but hardcoded URLs break silently. Example: href="{{ url_for('profile', username=user.name) }}" is preferred over href="/profile/{{ user.name }}".

Flask Hooks & Contexts

Flask Extensions by Popularity (Approximate Downloads/Week)

Most commonly used Flask extensions in the ecosystem

Databases with Flask-SQLAlchemy

Flask-SQLAlchemy is the most popular database extension. It provides an ORM layer and simplifies database configuration.

1from flask_sqlalchemy import SQLAlchemy 2from flask_migrate import Migrate 3 4app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' 5app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 6 7db = SQLAlchemy(app) 8migrate = Migrate(app, db) 9 10# Model definition 11class User(db.Model): 12 __tablename__ = 'users' 13 14 id = db.Column(db.Integer, primary_key=True) 15 username = db.Column(db.String(80), unique=True, nullable=False) 16 email = db.Column(db.String(120), unique=True, nullable=False) 17 created_at = db.Column(db.DateTime, server_default=db.func.now()) 18 19 # Relationship 20 posts = db.relationship('Post', backref='author', lazy=True) 21 22 def __repr__(self): 23 return f'<User {self.username}>' 24 25class Post(db.Model): 26 id = db.Column(db.Integer, primary_key=True) 27 title = db.Column(db.String(200), nullable=False) 28 content = db.Column(db.Text) 29 user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

Common SQLAlchemy column types & queries:

1# Column types available 2db.String(80) db.Text db.Integer 3db.Float db.Boolean db.DateTime 4db.Date db.LargeBinary db.Numeric 5db.Enum db.JSON db.ARRAY 6 7# Query operations 8User.query.all() # All records 9User.query.filter_by(username='alice').first() # Filter by exact 10User.query.filter(User.email.endswith('@org.com')).all() # SQL-like 11User.query.order_by(User.created_at.desc()).limit(10).all() 12User.query.paginate(page=1, per_page=20) # Pagination 13 14# CRUD Operations 15user = User(username='bob', email='bob@org.com') 16db.session.add(user) 17db.session.commit() 18 19user.username = 'bob_updated' 20db.session.commit() 21 22db.session.delete(user) 23db.session.commit()

SQLALCHEMY_DATABASE_URI Format Matters

Double-check your connection string format. Common mistakes include missing the /// for SQLite (which is file-based) vs // for remote databases.

  • SQLite: sqlite:////absolute/path/to/db.sqlite (3 slashes for relative, 4 for absolute)
  • PostgreSQL: postgresql://user:password@localhost:5432/mydb
  • MySQL: mysql://user:password@localhost/mydb
  • Never commit database URLs with credentials — use environment variables instead.

Building a Flask REST API Endpoint

  1. 1
    Step 1

    Use @app.route() with explicit HTTP methods. For REST APIs, be specific about allowed methods:

    1from flask import Blueprint 2 3api_bp = Blueprint('api', __name__, url_prefix='/api/v1') 4 5@api_bp.route('/users', methods=['GET', 'POST']) 6@api_bp.route('/users/<int:user_id>', methods=['GET', 'PUT', 'DELETE']) 7def users(user_id=None): 8 pass
  2. 2
    Step 2

    Extract and validate input from the request:

    1from flask import request 2 3# For GET: query parameters 4page = request.args.get('page', 1, type=int) 5per_page = request.args.get('per_page', 10, type=int) 6 7# For POST/PUT: JSON body 8data = request.get_json() 9username = data.get('username') 10email = data.get('email')
  3. 3
    Step 3

    Interact with the database and apply validation/rules:

    1if request.method == 'POST': 2 if User.query.filter_by(email=email).first(): 3 return {'error': 'Email already exists'}, 409 4 user = User(username=username, email=email) 5 db.session.add(user) 6 db.session.commit() 7 return {'id': user.id, 'username': user.username}, 201 8 9if request.method == 'GET': 10 if user_id: 11 user = User.query.get_or_404(user_id) 12 return {'id': user.id, 'username': user.username} 13 users = User.query.paginate(page=page, per_page=per_page) 14 return {'items': [u.to_dict() for u in users.items], 15 'total': users.total}
  4. 4
    Step 4

    Always return consistent JSON with appropriate HTTP status codes:

    1# 200 OK — Successful retrieval or update 2# 201 Created — Resource created successfully 3# 204 No Content — Successful deletion 4# 400 Bad Request — Invalid input 5# 404 Not Found — Resource doesn't exist 6# 409 Conflict — Duplicate resource 7# 422 Unprocessable — Validation failure

Flask Core Concepts

1 / 7
14%
Question · Term

What does @app.route() do?

Click to reveal
Answer · Definition

It registers a URL rule that maps a specific URL pattern to a Python view function. When a client requests that URL, Flask invokes the decorated function.

Flask Request Processing Lifecycle

Request Arrives

1

Client sends HTTP request; Werkzeug wraps it into a WSGI environ dict."

App & Request Contexts Pushed

2

Flask pushes the application context then the request context onto the context stack."

URL Matching

3

The URL map resolves the request path to a registered view function endpoint."

Before-Request Hooks

4

@app.before_request functions execute — can reject or augment the request early."

View Function Runs

5

The matched view function executes business logic and returns a value (string, dict, Response, tuple)."

After-Request Hooks

6

@app.after_request functions modify the response (e.g., add security headers)."

Teardown Hooks

7

@app.teardown_request and @app.teardown_appcontext clean up resources (close DB, etc.)."

Response Sent

8

The Response object is sent back through Werkzeug as an HTTP response to the client."

Blueprints — Modular Application Architecture

Blueprints let you organize your application into distinct, reusable components — essential for anything beyond a single-file app.

1# auth/routes.py 2from flask import Blueprint, render_template 3 4auth_bp = Blueprint('auth', __name__, 5 template_folder='templates', 6 static_folder='static', 7 url_prefix='/auth') 8 9@auth_bp.route('/login') 10def login(): 11 return render_template('auth/login.html') 12 13@auth_bp.route('/register') 14def register(): 15 return render_template('auth/register.html')
1# app.py — Register the blueprint 2from auth.routes import auth_bp 3 4app.register_blueprint(auth_bp) 5# Routes now available at /auth/login, /auth/register 6 7# Register with additional prefix 8app.register_blueprint(auth_bp, url_prefix='/v2/auth')

Recommended project structure:

myapp/
├── app/
│   ├── __init__.py          # create_app() factory
│   ├── models.py
│   ├── auth/
│   │   ├── __init__.py
│   │   ├── routes.py        # auth_bp blueprint
│   │   ├── forms.py
│   │   └── templates/auth/
│   ├── api/
│   │   ├── __init__.py
│   │   ├── routes.py        # api_bp blueprint
│   │   └── schemas.py
│   ├── main/
│   │   ├── __init__.py
│   │   ├── routes.py        # main_bp blueprint
│   │   └── templates/main/
│   ├── static/
│   └── templates/
│       └── base.html
├── migrations/
├── config.py
├── requirements.txt
└── run.py

Advanced Flask Topics

1from flask_login import LoginManager, UserMixin, \ 2 login_user, logout_user, login_required, current_user 3 4login_manager = LoginManager() 5login_manager.init_app(app) 6login_manager.login_view = 'auth.login' 7 8class User(UserMixin, db.Model): 9 id = db.Column(db.Integer, primary_key=True) 10 email = db.Column(db.String(120), unique=True) 11 12@login_manager.user_loader 13def load_user(user_id): 14 return User.query.get(int(user_id)) 15 16@app.route('/protected') 17@login_required 18def protected(): 19 return f'Hello, {current_user.email}!'

Flask Authentication Flow

Environment Variables for Configuration

Use python-dotenv with a .flaskenv file for Flask CLI settings and a .env file for secrets. Never commit .env to version control.

.flaskenv (committed to repo):

FLASK_APP=app
FLASK_ENV=development

.env (git-ignored):

SECRET_KEY=a-random-secret-key
DATABASE_URL=postgresql://user:pass@localhost/db

Access in code: app.config['SECRET_KEY'] or os.getenv('SECRET_KEY')

Knowledge Check

Question 1 of 5
Q1Single choice

What does the @app.route() decorator do in Flask?

Explore Related Topics

1

Blockchain Developer Skills: A Comprehensive Guide

This comprehensive guide maps the roadmap, skills, and resources required to become a competent blockchain developer.

  • Core skill tree spans computer science fundamentals, blockchain theory, smart contract coding, DApp front‑end, and security auditing.
  • Primary programming languages are Solidity (≈90% of contracts) and Rust (gaining traction for high‑performance chains).
  • Understanding consensus (PoW, PoS, DPoS, PoH) and tokenomics is vital for protocol design.
  • Smart contract security is critical, with total DeFi hacks (2021‑2024) $7.8 billion\geq \$7.8 \text{ billion} highlighting the risk.
  • Market demand is soaring (17.57Bin2023>17.57 B in 2023 → >942 B by 2032) and salaries range from 80kjuniorto80k junior to 500k+ senior roles.
2

Learn Python in 30 Days

Python is one of the most versatile and in-demand programming languages in the world. Created by Guido van Rossum and first released on February 20, 1991, Python has grown from a hobby project to the 1 programming language on the TIOBE Index as of 2024 . With over 18.2 million active developers worl

3

CSS Flexbox Cheat Sheet: The Complete Reference Guide

CSS Flexbox is a one‑dimensional layout model that uses a main axis (set by flex-direction) and a cross axis to control distribution and alignment of flex items within a container.

  • justify-content aligns items along the main axis, while align-items and align-content work on the cross axis (the latter only with wrapped lines).
  • Container properties (display, flex-direction, flex-wrap, justify-content, align-items, align-content, gap) manage group distribution; item properties (order, flex-grow, flex-shrink, flex-basis, flex, align-self) control individual behavior.
  • The flex shorthand (e.g., flex: 1, flex: none) combines grow, shrink, and basis; extra space is allocated by Item size=flex-basis+flex-growiflex-grow×free space\text{Item size} = \text{flex-basis} + \frac{\text{flex-grow}_i}{\sum \text{flex-grow}} \times \text{free space} and overflow is resolved by Shrink amounti=flex-shrinki×flex-basisi(flex-shrink×flex-basis)×overflow\text{Shrink amount}_i = \frac{\text{flex-shrink}_i \times \text{flex-basis}_i}{\sum (\text{flex-shrink} \times \text{flex-basis})} \times \text{overflow}.
  • Common patterns include perfect centering, navbar push‑right via margin-left:auto, Holy Grail layout, responsive card grids with gap, and sticky footers using column direction.
  • Beware of pitfalls: align-content has no effect on single‑line containers, and the default min-width:auto can prevent shrinking, requiring min-width:0 to avoid overflow.