Database with SQLAlchemy

Reviewed & published by Brayan K

Flask-SQLAlchemy is an extension that lets you define database tables as Python classes and query them with Python code instead of raw SQL, giving your Flask app a clean, object-oriented way to store and read data.

Part of the free Flask course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

In this lesson you'll configure a database, define your first model, create the tables, and add and read rows using the SQLAlchemy ORM.

What You'll Learn in This Lesson

1 Configuring the Database

Flask-SQLAlchemy is an ORM extension — it maps database rows to Python objects so you query data with Python instead of SQL.

You create a SQLAlchemy object bound to your app, and tell it where the database lives through the SQLALCHEMY_DATABASE_URI config. For learning, SQLite is ideal: the whole database is one file, no server required.

# Install the extension first
pip install flask-sqlalchemy

# Then in app.py:
#   app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
#   db = SQLAlchemy(app)

2 Defining a Model

A model is a Python class that inherits from db.Model. Each class becomes a table, and each attribute defined with db.Column becomes a column. Calling db.create_all() builds the tables.

The code below defines a User model with three columns and creates the table:

# app.py — define a model and create the table
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"

# Bind SQLAlchemy to the application.
db = SQLAlchemy(app)

# Each model class maps to one database table.
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), nullable=False)

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

# Create tables inside an application context.
with app.app_context():
    db.create_all()
    print("Tables created:", list(db.metadata.tables.keys()))

# ✅ Expected output:
# Tables created: ['user']

The primary_key=True column auto-numbers each row. The constraints unique and nullable are enforced by the database. Run flask run after this to serve an app backed by the table.

3 Adding and Reading Rows

To insert data you create a model instance, add it to the session with db.session.add(), then save it permanently with db.session.commit(). To read data you use User.query.

# app.py — insert rows and read them back
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
db = SQLAlchemy(app)

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), nullable=False)

with app.app_context():
    db.create_all()

    # Create and stage two new rows.
    db.session.add(User(username="ada", email="ada@example.com"))
    db.session.add(User(username="grace", email="grace@example.com"))

    # Persist them to the database.
    db.session.commit()

    # Read every row back out.
    for user in User.query.all():
        print(user.id, user.username, user.email)

    # Filter for a single row.
    ada = User.query.filter_by(username="ada").first()
    print("Found:", ada.email)

query.all() returns a list of every row; query.filter_by(...).first() returns a single matching object or None. Nothing is saved until commit() runs.

🔬 Anatomy of a Model

CodeWhat it does
db = SQLAlchemy(app)Binds the ORM to your application
class User(db.Model)Defines a table as a Python class
db.Column(db.Integer, ...)Declares a column and its type
db.create_all()Builds tables from your models
db.session.commit()Saves staged changes to the database

🎯 Your Turn: Fill in the Blanks

Complete the code below. Replace each ___ so it defines a Book model, creates the table, and adds one row.

# 🎯 YOUR TURN: replace each ___ to store a book
from flask import Flask
from flask_sqlalchemy import ___        # the extension class

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
db = ___(app)                            # bind the ORM

class Book(db.___):                      # inherit from the model base
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(120), nullable=False)

with app.app_context():
    db.___()                             # create the tables
    db.session.add(Book(title="Flask 101"))
    db.session.___()                     # save the row
    print(Book.query.all())

Common Errors & Quick Reference

❌ RuntimeError: Working outside of application context

Database calls like db.create_all() and query need an app context. Wrap them in with app.app_context(): when running outside a request.

❌ My new rows disappear after restart

You added them but never called db.session.commit(). Staged changes are only saved permanently when you commit the session.

TaskCommand / Code
Installpip install flask-sqlalchemy
Create tablesdb.create_all()
Add a rowdb.session.add(obj)
Read all rowsModel.query.all()

🏆 Mini Challenge: A Task Table

Build a small to-do database with one model and a few rows.

# 🏆 Mini Challenge: a to-do table
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///tasks.db"
db = SQLAlchemy(app)

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    done = db.Column(db.Boolean, default=False)

with app.app_context():
    db.create_all()
    db.session.add(Task(title="Learn SQLAlchemy"))
    db.session.add(Task(title="Build an app", done=True))
    db.session.commit()
    for task in Task.query.all():
        print(task.id, task.title, "done" if task.done else "todo")

❓ Frequently Asked Questions

Lesson complete — your app has a database!

You configured Flask-SQLAlchemy, defined a model, created tables with db.create_all(), and inserted and queried rows. Your data now persists between runs.

Practice quiz

What is Flask-SQLAlchemy?

  • A template engine
  • An ORM extension that maps database rows to Python objects
  • A migration-only tool
  • A WSGI server

Answer: An ORM extension that maps database rows to Python objects. Flask-SQLAlchemy integrates the SQLAlchemy ORM with Flask so you query data with Python objects instead of raw SQL.

Which base class does a model inherit from?

  • db.Model
  • db.Table
  • SQLAlchemy
  • db.Base

Answer: db.Model. Each model class inherits from db.Model, and each class becomes a database table.

Which config key tells Flask-SQLAlchemy where the database lives?

  • DATABASE_PATH
  • DB_URI
  • SQLALCHEMY_DATABASE_URI
  • SQLALCHEMY_URL

Answer: SQLALCHEMY_DATABASE_URI. You set app.config['SQLALCHEMY_DATABASE_URI'], for example to 'sqlite:///app.db'.

How do you declare a column in a model?

  • db.Field(...)
  • Column.new(...)
  • db.Attribute(...)
  • db.Column(db.Integer, ...)

Answer: db.Column(db.Integer, ...). Each attribute defined with db.Column(type, ...) becomes a column in the table.

Which call builds the tables from your models?

  • db.create_all()
  • db.build()
  • db.migrate()
  • db.session.commit()

Answer: db.create_all(). db.create_all() creates any tables that do not yet exist based on your model definitions.

How do you stage a new row for insertion?

  • db.add(obj)
  • db.session.add(obj)
  • obj.save()
  • db.insert(obj)

Answer: db.session.add(obj). You add a model instance to the session with db.session.add(obj) before committing.

What permanently saves staged changes to the database?

  • db.flush()
  • db.save()
  • db.session.commit()
  • db.persist()

Answer: db.session.commit(). Nothing is saved until db.session.commit() runs, which writes the staged changes.

Which SQLite URI stores data in a file named app.db?

  • sqlite://app.db
  • file://app.db
  • sqlite:app.db
  • sqlite:///app.db

Answer: sqlite:///app.db. 'sqlite:///app.db' stores the whole database in a single app.db file next to your project.

How do you read every row from the User model?

  • User.query.all()
  • User.all()
  • db.query(User)
  • User.rows()

Answer: User.query.all(). Model.query.all() returns a list of every row in the table.

Why must db.create_all() run inside an application context?

  • To compress the file
  • To enable migrations
  • Because database calls need an active app context
  • To speed up queries

Answer: Because database calls need an active app context. Outside a request you wrap database calls in 'with app.app_context():' or you get a RuntimeError about working outside of application context.

Continue this course

Frequently asked questions

What is Flask-SQLAlchemy?

Flask-SQLAlchemy is an extension that integrates the SQLAlchemy ORM with Flask. It lets you define database tables as Python classes (models) and query them with Python instead of writing raw SQL.

What is an ORM?

An ORM (Object-Relational Mapper) maps database rows to Python objects. With SQLAlchemy, each model class becomes a table and each instance becomes a row, so you work with normal Python objects instead of SQL strings.

How do I create the database tables?

Define your model classes inheriting from db.Model, then call db.create_all() inside an application context. This creates any tables that do not yet exist based on your model definitions.

What database should I use to start?

SQLite is perfect for learning — it stores the whole database in a single file and needs no separate server. Set SQLALCHEMY_DATABASE_URI to 'sqlite:///app.db' and Flask-SQLAlchemy handles the rest.