Flask Quick Reference
Everything you need day‑to‑day – the lightweight Python web framework.
What is Flask?
- Minimalist Python web framework
- "Micro" framework – flexible and extensible
- Built on Werkzeug WSGI and Jinja2 templating
- Great for APIs, small to medium projects
- Extensible with extensions (Flask‑SQLAlchemy, Flask‑WTF, Flask‑Login)
Installation & Setup
pip install flask
# Basic application
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
Run Commands
python app.py flask run # uses app.py by default flask run --debug # debug mode flask run --host=0.0.0.0 --port=5000 # Set environment variables export FLASK_APP=app.py export FLASK_ENV=development export FLASK_DEBUG=1
Routing
@app.route('/')
def home():
return 'Home'
# Dynamic routes
@app.route('/user/<name>')
def user(name):
return f'Hello, {name}'
@app.route('/post/<int:post_id>')
def post(post_id):
return f'Post {post_id}'
# Methods
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return 'Login POST'
return 'Login GET'
# URL building
url_for('user', name='Alice') # /user/Alice
Route Types
<string>– default, any string<int>– integer<float>– floating point<path>– path with slashes<uuid>– UUID
Request & Response
Request Object
from flask import request # Query parameters request.args.get('key') request.args.get('key', default='default') request.args.getlist('key') // multiple values # Form data request.form.get('username') request.form.getlist('items') # JSON data request.json request.get_json() # Headers request.headers.get('User-Agent') # Files request.files.get('file') file.save('uploaded.txt') # Cookies request.cookies.get('session_id') # URL components request.url request.path request.method request.endpoint
Response Object
from flask import make_response, jsonify # Simple response return 'Hello', 200 # JSON response return jsonify({'message': 'Hello'}) # Status codes return 'Not Found', 404 # Custom response resp = make_response('Hello', 200) resp.headers['X-Custom'] = 'value' resp.set_cookie('key', 'value') return resp # Redirect from flask import redirect, url_for return redirect(url_for('home')) return redirect('/', code=302) # Abort from flask import abort abort(404) abort(401, 'Unauthorized')
Templates (Jinja2)
Setup
from flask import render_template
@app.route('/')
def home():
return render_template('index.html', name='Alice')
Template Syntax
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
{% if user %}
<p>Welcome, {{ user.username }}</p>
{% else %}
<p>Please login</p>
{% endif %}
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{{ name|upper }}
{{ name|lower }}
{{ name|title }}
{{ text|truncate(50) }}
{{ date|datetime }}
{{ value|default('N/A') }}
{% include 'header.html' %}
{% extends 'base.html' %}
{% block content %}
<p>Page content</p>
{% endblock %}
</body>
</html>
Custom Filters
@app.template_filter('datetime')
def format_datetime(value):
return value.strftime('%Y-%m-%d %H:%M:%S')
Forms (Flask‑WTF)
pip install flask-wtf # forms.py from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import DataRequired, Email, Length class LoginForm(FlaskForm): email = StringField('Email', validators=[DataRequired(), Email()]) password = PasswordField('Password', validators=[DataRequired(), Length(min=6)]) submit = SubmitField('Login') # routes.py from forms import LoginForm @app.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): email = form.email.data password = form.password.data return redirect(url_for('home')) return render_template('login.html', form=form)
Template
<form method="post">
{{ form.csrf_token }}
{{ form.email.label }} {{ form.email(size=20) }}
{{ form.password.label }} {{ form.password(size=20) }}
{{ form.submit() }}
</form>
// With Bootstrap styling
{% for field in form %}
{% if field.type != 'SubmitField' %}
{{ field.label }} {{ field(class="form-control") }}
{% for error in field.errors %}
<span class="error">{{ error }}</span>
{% endfor %}
{% endif %}
{% endfor %}
{{ form.submit(class="btn btn-primary") }}
Database (SQLAlchemy)
pip install flask-sqlalchemy flask-migrate # app.py from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db) # models.py class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) def __repr__(self): return f'<User {self.username}>' # Commands flask db init # first time flask db migrate -m "message" flask db upgrade # CRUD # Create user = User(username='alice', email='alice@ex.com') db.session.add(user) db.session.commit() # Read users = User.query.all() user = User.query.filter_by(username='alice').first() user = User.query.get(1) # Update user.email = 'new@ex.com' db.session.commit() # Delete db.session.delete(user) db.session.commit()
Authentication (Flask‑Login)
pip install flask-login
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
login_manager = LoginManager(app)
login_manager.login_view = 'login'
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user = User.query.filter_by(username=request.form['username']).first()
if user and check_password_hash(user.password, request.form['password']):
login_user(user)
return redirect(request.args.get('next') or url_for('home'))
return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('home'))
Blueprints (Modular Structure)
# auth.py (blueprint) from flask import Blueprint, render_template bp = Blueprint('auth', __name__, url_prefix='/auth') @bp.route('/login') def login(): return render_template('auth/login.html') # app.py from auth import bp as auth_bp app.register_blueprint(auth_bp)
Error Handling
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_error(error):
return render_template('500.html'), 500
Configuration
# config.py import os class Config: SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key' SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db' SQLALCHEMY_TRACK_MODIFICATIONS = False DEBUG = True class ProductionConfig(Config): DEBUG = False SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') # app.py app.config.from_object(Config) app.config.from_pyfile('config.py') # Environment variables import os SECRET_KEY = os.getenv('SECRET_KEY')
Cookies & Sessions
# Sessions (client-side, signed) from flask import session session['user_id'] = 123 user_id = session.get('user_id') # Cookies from flask import make_response resp = make_response(render_template('index.html')) resp.set_cookie('theme', 'dark', max_age=3600) resp.delete_cookie('theme') return resp
Static Files
# Serve static files from /static directory # In template: <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> <script src="{{ url_for('static', filename='script.js') }}"></script> <img src="{{ url_for('static', filename='images/logo.png') }}">
Flask Extensions
- Flask‑SQLAlchemy – ORM
- Flask‑Migrate – DB migrations
- Flask‑WTF – Forms
- Flask‑Login – Authentication
- Flask‑CORS – Cross‑Origin
- Flask‑RESTful – REST APIs
- Flask‑Mail – Email
- Flask‑Bcrypt – Password hashing
- Flask‑JWT‑Extended – JWT
- Flask‑Admin – Admin panel
- Flask‑DebugToolbar – Debug
- Flask‑Limiter – Rate limiting
Best Practices
- Use a config class – for environment‑specific settings.
- Use blueprints – for modular, organised code.
- Use environment variables – for sensitive data.
- Use migrations – Flask‑Migrate for DB schema changes.
- Validate user input – use WTForms.
- Hash passwords – use Flask‑Bcrypt or Werkzeug.
- Use `@login_required` – protect routes.
- Write tests – use pytest.
- Use application factories – for flexibility.
- Use `url_for` – instead of hardcoding URLs.
- Use `request.parsed_json` – for better error handling with JSON.
- Keep templates DRY – use template inheritance.
- Use logging – for debugging and monitoring.
- Use
gobject – for request‑scoped data.
📌 Quick Reference
Create app:
Routes:
Request:
Templates:
Forms: Flask‑WTF, WTForms, validation
Database: Flask‑SQLAlchemy, ORM, migrations
Auth: Flask‑Login,
Structure: Blueprints, application factory, config
Run:
Flask(__name__)Routes:
@app.route('/path')Request:
request.args, request.form, request.jsonTemplates:
render_template(), Jinja2Forms: Flask‑WTF, WTForms, validation
Database: Flask‑SQLAlchemy, ORM, migrations
Auth: Flask‑Login,
@login_requiredStructure: Blueprints, application factory, config
Run:
flask run, --debug