Flask Essentials
Flask web framework essentials for building web applications and APIs.
Installation
1pip install flask
2
3# With extensions
4pip install flask flask-sqlalchemy flask-migrate flask-login flask-wtf flask-cors
Basic Flask App
1from flask import Flask
2
3app = Flask(__name__)
4
5@app.route('/')
6def hello():
7 return 'Hello, World!'
8
9@app.route('/user/<username>')
10def show_user(username):
11 return f'User: {username}'
12
13@app.route('/post/<int:post_id>')
14def show_post(post_id):
15 return f'Post ID: {post_id}'
16
17if __name__ == '__main__':
18 app.run(debug=True)
Request and Response
1from flask import Flask, request, jsonify, make_response
2
3app = Flask(__name__)
4
5@app.route('/data', methods=['GET', 'POST'])
6def handle_data():
7 if request.method == 'POST':
8 # Get JSON data
9 data = request.get_json()
10
11 # Get form data
12 name = request.form.get('name')
13
14 # Get query parameters
15 page = request.args.get('page', 1, type=int)
16
17 # Get headers
18 auth = request.headers.get('Authorization')
19
20 return jsonify({'message': 'Data received', 'data': data})
21
22 return jsonify({'message': 'Send POST request'})
23
24@app.route('/custom-response')
25def custom_response():
26 response = make_response(jsonify({'status': 'ok'}), 200)
27 response.headers['X-Custom-Header'] = 'value'
28 return response
29
30@app.route('/download')
31def download_file():
32 from flask import send_file
33 return send_file('path/to/file.pdf', as_attachment=True)
Templates (Jinja2)
1from flask import Flask, render_template
2
3app = Flask(__name__)
4
5@app.route('/hello/<name>')
6def hello(name):
7 return render_template('hello.html', name=name)
8
9@app.route('/users')
10def users():
11 users = [
12 {'id': 1, 'name': 'Alice'},
13 {'id': 2, 'name': 'Bob'}
14 ]
15 return render_template('users.html', users=users)
1<!-- templates/hello.html -->
2<!DOCTYPE html>
3<html>
4<head>
5 <title>Hello</title>
6</head>
7<body>
8 <h1>Hello, {{ name }}!</h1>
9 {% if name == 'Admin' %}
10 <p>Welcome, administrator!</p>
11 {% endif %}
12</body>
13</html>
1<!-- templates/users.html -->
2<!DOCTYPE html>
3<html>
4<head>
5 <title>Users</title>
6</head>
7<body>
8 <h1>Users</h1>
9 <ul>
10 {% for user in users %}
11 <li>{{ user.name }} (ID: {{ user.id }})</li>
12 {% endfor %}
13 </ul>
14</body>
15</html>
Blueprints (Modular Apps)
1# app.py
2from flask import Flask
3from blueprints.auth import auth_bp
4from blueprints.api import api_bp
5
6app = Flask(__name__)
7
8app.register_blueprint(auth_bp, url_prefix='/auth')
9app.register_blueprint(api_bp, url_prefix='/api')
10
11if __name__ == '__main__':
12 app.run(debug=True)
1# blueprints/auth.py
2from flask import Blueprint, request, jsonify
3
4auth_bp = Blueprint('auth', __name__)
5
6@auth_bp.route('/login', methods=['POST'])
7def login():
8 data = request.get_json()
9 username = data.get('username')
10 password = data.get('password')
11
12 # Authenticate user
13 if username == 'admin' and password == 'secret':
14 return jsonify({'token': 'abc123'})
15
16 return jsonify({'error': 'Invalid credentials'}), 401
17
18@auth_bp.route('/logout', methods=['POST'])
19def logout():
20 return jsonify({'message': 'Logged out'})
1# blueprints/api.py
2from flask import Blueprint, jsonify
3
4api_bp = Blueprint('api', __name__)
5
6@api_bp.route('/users')
7def get_users():
8 users = [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]
9 return jsonify(users)
10
11@api_bp.route('/users/<int:user_id>')
12def get_user(user_id):
13 user = {'id': user_id, 'name': 'Alice'}
14 return jsonify(user)
Database (Flask-SQLAlchemy)
1from flask import Flask, jsonify
2from flask_sqlalchemy import SQLAlchemy
3from datetime import datetime
4
5app = Flask(__name__)
6app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
7app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
8
9db = SQLAlchemy(app)
10
11class User(db.Model):
12 id = db.Column(db.Integer, primary_key=True)
13 username = db.Column(db.String(80), unique=True, nullable=False)
14 email = db.Column(db.String(120), unique=True, nullable=False)
15 created_at = db.Column(db.DateTime, default=datetime.utcnow)
16 posts = db.relationship('Post', backref='author', lazy=True)
17
18 def to_dict(self):
19 return {
20 'id': self.id,
21 'username': self.username,
22 'email': self.email,
23 'created_at': self.created_at.isoformat()
24 }
25
26class Post(db.Model):
27 id = db.Column(db.Integer, primary_key=True)
28 title = db.Column(db.String(200), nullable=False)
29 content = db.Column(db.Text, nullable=False)
30 created_at = db.Column(db.DateTime, default=datetime.utcnow)
31 user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
32
33 def to_dict(self):
34 return {
35 'id': self.id,
36 'title': self.title,
37 'content': self.content,
38 'created_at': self.created_at.isoformat(),
39 'author': self.author.username
40 }
41
42# Create tables
43with app.app_context():
44 db.create_all()
45
46@app.route('/users', methods=['GET', 'POST'])
47def users():
48 if request.method == 'POST':
49 data = request.get_json()
50 user = User(username=data['username'], email=data['email'])
51 db.session.add(user)
52 db.session.commit()
53 return jsonify(user.to_dict()), 201
54
55 users = User.query.all()
56 return jsonify([user.to_dict() for user in users])
57
58@app.route('/users/<int:user_id>')
59def get_user(user_id):
60 user = User.query.get_or_404(user_id)
61 return jsonify(user.to_dict())
62
63@app.route('/posts', methods=['GET', 'POST'])
64def posts():
65 if request.method == 'POST':
66 data = request.get_json()
67 post = Post(
68 title=data['title'],
69 content=data['content'],
70 user_id=data['user_id']
71 )
72 db.session.add(post)
73 db.session.commit()
74 return jsonify(post.to_dict()), 201
75
76 posts = Post.query.all()
77 return jsonify([post.to_dict() for post in posts])
Database Migrations (Flask-Migrate)
1from flask import Flask
2from flask_sqlalchemy import SQLAlchemy
3from flask_migrate import Migrate
4
5app = Flask(__name__)
6app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
7
8db = SQLAlchemy(app)
9migrate = Migrate(app, db)
10
11class User(db.Model):
12 id = db.Column(db.Integer, primary_key=True)
13 username = db.Column(db.String(80), nullable=False)
1# Initialize migrations
2flask db init
3
4# Create migration
5flask db migrate -m "Initial migration"
6
7# Apply migration
8flask db upgrade
9
10# Rollback
11flask db downgrade
12
13# Show current version
14flask db current
15
16# Show migration history
17flask db history
Authentication (Flask-Login)
1from flask import Flask, request, jsonify
2from flask_sqlalchemy import SQLAlchemy
3from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
4from werkzeug.security import generate_password_hash, check_password_hash
5
6app = Flask(__name__)
7app.config['SECRET_KEY'] = 'your-secret-key'
8app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
9
10db = SQLAlchemy(app)
11login_manager = LoginManager(app)
12
13class User(UserMixin, db.Model):
14 id = db.Column(db.Integer, primary_key=True)
15 username = db.Column(db.String(80), unique=True, nullable=False)
16 password_hash = db.Column(db.String(128))
17
18 def set_password(self, password):
19 self.password_hash = generate_password_hash(password)
20
21 def check_password(self, password):
22 return check_password_hash(self.password_hash, password)
23
24@login_manager.user_loader
25def load_user(user_id):
26 return User.query.get(int(user_id))
27
28@app.route('/register', methods=['POST'])
29def register():
30 data = request.get_json()
31 user = User(username=data['username'])
32 user.set_password(data['password'])
33 db.session.add(user)
34 db.session.commit()
35 return jsonify({'message': 'User created'}), 201
36
37@app.route('/login', methods=['POST'])
38def login():
39 data = request.get_json()
40 user = User.query.filter_by(username=data['username']).first()
41
42 if user and user.check_password(data['password']):
43 login_user(user)
44 return jsonify({'message': 'Logged in'})
45
46 return jsonify({'error': 'Invalid credentials'}), 401
47
48@app.route('/logout')
49@login_required
50def logout():
51 logout_user()
52 return jsonify({'message': 'Logged out'})
53
54@app.route('/profile')
55@login_required
56def profile():
57 return jsonify({
58 'id': current_user.id,
59 'username': current_user.username
60 })
Forms (Flask-WTF)
1from flask import Flask, render_template, redirect, url_for, flash
2from flask_wtf import FlaskForm
3from wtforms import StringField, PasswordField, SubmitField
4from wtforms.validators import DataRequired, Email, Length
5
6app = Flask(__name__)
7app.config['SECRET_KEY'] = 'your-secret-key'
8
9class LoginForm(FlaskForm):
10 username = StringField('Username', validators=[DataRequired(), Length(min=3, max=80)])
11 password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
12 submit = SubmitField('Login')
13
14class RegistrationForm(FlaskForm):
15 username = StringField('Username', validators=[DataRequired(), Length(min=3, max=80)])
16 email = StringField('Email', validators=[DataRequired(), Email()])
17 password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
18 submit = SubmitField('Register')
19
20@app.route('/login', methods=['GET', 'POST'])
21def login():
22 form = LoginForm()
23 if form.validate_on_submit():
24 username = form.username.data
25 password = form.password.data
26 # Authenticate user
27 flash('Login successful!', 'success')
28 return redirect(url_for('index'))
29 return render_template('login.html', form=form)
30
31@app.route('/register', methods=['GET', 'POST'])
32def register():
33 form = RegistrationForm()
34 if form.validate_on_submit():
35 # Create user
36 flash('Registration successful!', 'success')
37 return redirect(url_for('login'))
38 return render_template('register.html', form=form)
1<!-- templates/login.html -->
2<!DOCTYPE html>
3<html>
4<head>
5 <title>Login</title>
6</head>
7<body>
8 <h1>Login</h1>
9 {% with messages = get_flashed_messages(with_categories=true) %}
10 {% if messages %}
11 {% for category, message in messages %}
12 <div class="alert alert-{{ category }}">{{ message }}</div>
13 {% endfor %}
14 {% endif %}
15 {% endwith %}
16
17 <form method="POST">
18 {{ form.hidden_tag() }}
19 <div>
20 {{ form.username.label }}
21 {{ form.username(size=32) }}
22 {% if form.username.errors %}
23 <span style="color: red;">{{ form.username.errors[0] }}</span>
24 {% endif %}
25 </div>
26 <div>
27 {{ form.password.label }}
28 {{ form.password(size=32) }}
29 {% if form.password.errors %}
30 <span style="color: red;">{{ form.password.errors[0] }}</span>
31 {% endif %}
32 </div>
33 <div>
34 {{ form.submit() }}
35 </div>
36 </form>
37</body>
38</html>
CORS (Flask-CORS)
1from flask import Flask, jsonify
2from flask_cors import CORS
3
4app = Flask(__name__)
5
6# Enable CORS for all routes
7CORS(app)
8
9# Or configure specific origins
10CORS(app, resources={
11 r"/api/*": {
12 "origins": ["http://localhost:3000", "https://example.com"],
13 "methods": ["GET", "POST", "PUT", "DELETE"],
14 "allow_headers": ["Content-Type", "Authorization"]
15 }
16})
17
18@app.route('/api/data')
19def get_data():
20 return jsonify({'data': 'value'})
Error Handling
1from flask import Flask, jsonify
2
3app = Flask(__name__)
4
5@app.errorhandler(404)
6def not_found(error):
7 return jsonify({'error': 'Not found'}), 404
8
9@app.errorhandler(500)
10def internal_error(error):
11 return jsonify({'error': 'Internal server error'}), 500
12
13@app.errorhandler(Exception)
14def handle_exception(e):
15 app.logger.error(f'Unhandled exception: {e}')
16 return jsonify({'error': 'Something went wrong'}), 500
17
18class ValidationError(Exception):
19 pass
20
21@app.errorhandler(ValidationError)
22def handle_validation_error(e):
23 return jsonify({'error': str(e)}), 400
24
25@app.route('/validate')
26def validate():
27 raise ValidationError('Invalid input')
Configuration
1from flask import Flask
2import os
3
4app = Flask(__name__)
5
6# Configuration from object
7class Config:
8 SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key'
9 SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
10 SQLALCHEMY_TRACK_MODIFICATIONS = False
11 DEBUG = False
12 TESTING = False
13
14class DevelopmentConfig(Config):
15 DEBUG = True
16
17class ProductionConfig(Config):
18 DEBUG = False
19
20class TestingConfig(Config):
21 TESTING = True
22 SQLALCHEMY_DATABASE_URI = 'sqlite:///test.db'
23
24# Load config
25config_name = os.environ.get('FLASK_ENV', 'development')
26if config_name == 'production':
27 app.config.from_object(ProductionConfig)
28elif config_name == 'testing':
29 app.config.from_object(TestingConfig)
30else:
31 app.config.from_object(DevelopmentConfig)
32
33# Or from file
34# app.config.from_pyfile('config.py')
35
36# Or from environment variable
37# app.config.from_envvar('APP_CONFIG_FILE')
Logging
1from flask import Flask
2import logging
3from logging.handlers import RotatingFileHandler
4import os
5
6app = Flask(__name__)
7
8if not app.debug:
9 if not os.path.exists('logs'):
10 os.mkdir('logs')
11
12 file_handler = RotatingFileHandler(
13 'logs/app.log',
14 maxBytes=10240,
15 backupCount=10
16 )
17 file_handler.setFormatter(logging.Formatter(
18 '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
19 ))
20 file_handler.setLevel(logging.INFO)
21 app.logger.addHandler(file_handler)
22
23 app.logger.setLevel(logging.INFO)
24 app.logger.info('Application startup')
25
26@app.route('/')
27def index():
28 app.logger.info('Index page accessed')
29 return 'Hello, World!'
Testing
1# test_app.py
2import pytest
3from app import app, db, User
4
5@pytest.fixture
6def client():
7 app.config['TESTING'] = True
8 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
9
10 with app.test_client() as client:
11 with app.app_context():
12 db.create_all()
13 yield client
14 with app.app_context():
15 db.drop_all()
16
17def test_index(client):
18 response = client.get('/')
19 assert response.status_code == 200
20 assert b'Hello' in response.data
21
22def test_create_user(client):
23 response = client.post('/users', json={
24 'username': 'testuser',
25 'email': 'test@example.com'
26 })
27 assert response.status_code == 201
28 data = response.get_json()
29 assert data['username'] == 'testuser'
30
31def test_get_users(client):
32 response = client.get('/users')
33 assert response.status_code == 200
34 data = response.get_json()
35 assert isinstance(data, list)
1# Run tests
2pytest test_app.py
3
4# With coverage
5pytest --cov=app test_app.py
RESTful API Example
1from flask import Flask, request, jsonify
2from flask_sqlalchemy import SQLAlchemy
3
4app = Flask(__name__)
5app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///api.db'
6db = SQLAlchemy(app)
7
8class Item(db.Model):
9 id = db.Column(db.Integer, primary_key=True)
10 name = db.Column(db.String(100), nullable=False)
11 description = db.Column(db.Text)
12 price = db.Column(db.Float, nullable=False)
13
14 def to_dict(self):
15 return {
16 'id': self.id,
17 'name': self.name,
18 'description': self.description,
19 'price': self.price
20 }
21
22with app.app_context():
23 db.create_all()
24
25# List all items
26@app.route('/api/items', methods=['GET'])
27def get_items():
28 items = Item.query.all()
29 return jsonify([item.to_dict() for item in items])
30
31# Get single item
32@app.route('/api/items/<int:item_id>', methods=['GET'])
33def get_item(item_id):
34 item = Item.query.get_or_404(item_id)
35 return jsonify(item.to_dict())
36
37# Create item
38@app.route('/api/items', methods=['POST'])
39def create_item():
40 data = request.get_json()
41 item = Item(
42 name=data['name'],
43 description=data.get('description', ''),
44 price=data['price']
45 )
46 db.session.add(item)
47 db.session.commit()
48 return jsonify(item.to_dict()), 201
49
50# Update item
51@app.route('/api/items/<int:item_id>', methods=['PUT'])
52def update_item(item_id):
53 item = Item.query.get_or_404(item_id)
54 data = request.get_json()
55
56 item.name = data.get('name', item.name)
57 item.description = data.get('description', item.description)
58 item.price = data.get('price', item.price)
59
60 db.session.commit()
61 return jsonify(item.to_dict())
62
63# Delete item
64@app.route('/api/items/<int:item_id>', methods=['DELETE'])
65def delete_item(item_id):
66 item = Item.query.get_or_404(item_id)
67 db.session.delete(item)
68 db.session.commit()
69 return '', 204
70
71if __name__ == '__main__':
72 app.run(debug=True)
Deployment
Gunicorn
1# Install
2pip install gunicorn
3
4# Run
5gunicorn -w 4 -b 0.0.0.0:8000 app:app
6
7# With config file
8gunicorn -c gunicorn_config.py app:app
1# gunicorn_config.py
2bind = "0.0.0.0:8000"
3workers = 4
4worker_class = "sync"
5worker_connections = 1000
6timeout = 30
7keepalive = 2
8errorlog = "logs/gunicorn-error.log"
9accesslog = "logs/gunicorn-access.log"
10loglevel = "info"
Docker
1# Dockerfile
2FROM python:3.11-slim
3
4WORKDIR /app
5
6COPY requirements.txt .
7RUN pip install --no-cache-dir -r requirements.txt
8
9COPY . .
10
11EXPOSE 8000
12
13CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]
1# docker-compose.yml
2version: '3.8'
3
4services:
5 web:
6 build: .
7 ports:
8 - "8000:8000"
9 environment:
10 - FLASK_ENV=production
11 - DATABASE_URL=postgresql://user:pass@db:5432/mydb
12 depends_on:
13 - db
14
15 db:
16 image: postgres:15
17 environment:
18 - POSTGRES_USER=user
19 - POSTGRES_PASSWORD=pass
20 - POSTGRES_DB=mydb
21 volumes:
22 - postgres_data:/var/lib/postgresql/data
23
24volumes:
25 postgres_data:
Related Snippets
- Click CLI Framework
Building CLI applications with Click in Python - FastAPI with OpenAPI
FastAPI with automatic OpenAPI documentation using Pydantic models and … - Function Timing Decorator
Decorator to measure function execution time - LangChain Chatbot with Tools
Simple stdin chatbot using LangChain with tool calling (OpenRouter). … - Pandas DataFrames Essential Patterns
Essential patterns for working with Pandas DataFrames: creation, manipulation, … - Pydantic Data Validation
Pydantic - Data validation using Python type hints. Installation 1pip install … - Python Dataclasses
Python dataclasses for clean, boilerplate-free data structures. Basic Usage … - Python Metaclasses
Python metaclasses with visual explanations using Mermaid diagrams. What are … - Python Virtual Environments
Managing Python virtual environments and dependencies - Random Forests in Depth
Comprehensive guide to Random Forests: theory, implementation, tuning, and … - Scikit-learn Common Patterns
Common patterns and workflows for scikit-learn: preprocessing, model training, …