Flask doesn’t include a database layer. Flask-SQLAlchemy integrates SQLAlchemy ORM seamlessly.

Setup

  pip install flask-sqlalchemy flask-migrate
  
  # app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    db.init_app(app)
    migrate.init_app(app, db)

    from .routes import main
    app.register_blueprint(main)

    return app
  

Define Models

  # app/models.py
from app import db
from datetime import datetime

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)
    posts = db.relationship('Post', backref='author', lazy=True)

    def __repr__(self):
        return f'<User {self.username}>'

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    body = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
  

Migrations

  flask db init
flask db migrate -m "Initial migration"
flask db upgrade
  

CRUD Operations

  from app.models import User, Post
from app import db

# Create
user = User(username='alice', email='[email protected]')
db.session.add(user)
db.session.commit()

# Read
users = User.query.all()
alice = User.query.filter_by(username='alice').first()

# Update
alice.email = '[email protected]'
db.session.commit()

# Delete
db.session.delete(alice)
db.session.commit()
  

Using Models in Routes

  from flask import Blueprint, jsonify, request
from app.models import Post
from app import db

api = Blueprint('api', __name__, url_prefix='/api')

@api.route('/posts', methods=['GET'])
def get_posts():
    posts = Post.query.order_by(Post.created_at.desc()).all()
    return jsonify([{
        'id': p.id,
        'title': p.title,
        'body': p.body,
    } for p in posts])

@api.route('/posts', methods=['POST'])
def create_post():
    data = request.get_json()
    post = Post(title=data['title'], body=data['body'], user_id=1)
    db.session.add(post)
    db.session.commit()
    return jsonify({'id': post.id}), 201
  

Production Database

For PostgreSQL:

  app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://user:pass@localhost/mydb'
  

Install driver: pip install psycopg2-binary

Flask-SQLAlchemy gives you Django-like ORM power with Flask’s lightweight flexibility.