Database Integration with Flask-SQLAlchemy

Database Integration with Flask-SQLAlchemy

Relational databases are widely used in web applications. These databases organize data into tables with fixed columns and variable rows, where columns represent the attributes of entities being modeled.

Flask doesn't impose any restrictions on database selection, allowing developers to choose between SQL or NoSQL solutions. For more convenient database operations, SQLAlchemy—an Object-Relational Mapping (ORM) framework similar to Django's ORM—can be utilized.

Flask-SQLAlchemy Extension

SQLAlchemy serves as an abstraction layer over databases, enabling developers to interact with databases through Python objects rather than raw SQL statements. This approach trades some performance overhead for significantly improved development efficiency.

Flask-SQLAlchemy is a Flask extension that simplifies SQLAlchemy operations, providing both high-level ORM functionality and access to low-level database operations.

Installation

To begin using Flask-SQLAlchemy, install it via pip:

pip install flask-sqlalchemy

For MySQL connections, you'll also need to install Flask-MySQLdb:

pip install flask-mysqldb

Configuring Flask-SQLAlchemy

In Flask-SQLAlchemy, databases are specified using URIs, and the application's database must be configured in the Flask configuration object's SQLALCHEMY_DATABASE_URI key.

Basic Database Configuration

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost:3306/database_name'

Additional Configuration Options

# Enable or disable modification tracking
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

# Display original SQL statements during queries
app.config['SQLALCHEMY_ECHO'] = True
Configuration Key Description
SQLALCHEMY_DATABASE_URI Database URI for connection. Examples: sqlite:////tmp/test.db, mysql://user:pass@server/db
SQLALCHEMY_BINDS Dictionary mapping binds to connection URIs for multiple databases
SQLALCHEMY_ECHO If True, SQLAlchemy logs all statements to stderr (prints SQL)
SQLALCHEMY_RECORD_QUERIES Enable or disable query recording, useful for debugging
SQLALCHEMY_POOL_SIZE Size of database connection pool (default is 5)
SQLALCHEMY_POOL_TIMEOUT Connection timeout for the pool (default is 10 seconds)
SQLALCHEMY_POOL_RECYCLE Seconds after which connections are recycled (important for MySQL)

Connecting to Different Databases

Here are connection strings for common database systems:

PostgreSQL

postgresql://username:password@localhost/database_name

MySQL

mysql://username:password@localhost/database_name

Oracle

oracle://username:password@127.0.0.1:1521/service_name

SQLite

Note the four leading slashes for absolute paths:

sqlite:////absolute/path/to/database.db

Common SQLAlchemy Field Types

Type Name Python Type Description
Integer int Standard integer, typically 32-bit
SmallInteger int Small-range integer, typically 16-bit
BigInteger int or long Integer with unlimited precision
Float float Floating-point number
Numeric decimal.Decimal Fixed-point or floating-point number
String str Variable-length string
Text str Variable-length string optimized for longer content
Boolean bool Boolean value (True/False)
Date datetime.date Date value
DateTime datetime.datetime Date and time value
LargeBinary bytes Binary data

Common SQLAlchemy Column Options

Option Description
primary_key If True, designates the column as the table's primary key
unique If True, ensures the column contains only unique values
index If True, creates an index on the column for faster queries
nullable If True, allows NULL values in the column
default Specifies a default value for the column

Common SQLAlchemy Relationship Options

Option Description
backref Adds a reverse reference in the related model
primary join Explicitly specifies the join condition between models
uselist If False, uses scalar values instead of lists
order_by Specifies sorting order for related records
secondary Specifies the association table for many-to-many relationships

Basic Database Operations

In Flask-SQLAlchemy, insert, update, and delete operations are managed through database sessions. Data must be added to the session before committing changes to the database using the commit() method.

Query operations are performed through the query object, which allows filtering for more precise database searches.

Defining Models

Models can be defined in view functions with an explicit table name:

# Explicitly specify table name; if omitted, defaults to class name
__tablename__ = "explicit_table_name"

Example Application Setup

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# Database connection settings
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:password@localhost:3306/my_database'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Initialize SQLAlchemy and associate with the current app
db = SQLAlchemy(app)

# Define model classes
class Department(db.Model):
    __tablename__ = 'departments'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)

class Employee(db.Model):
    __tablename__ = 'employees'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    email = db.Column(db.String(64), default='')
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))

@app.route('/')
def index():
    return 'Hello World'

if __name__ == '__main__':
    # Drop all existing tables
    db.drop_all()
    # Create all tables
    db.create_all()
    app.run(debug=True)

Model Relationships

One-to-Many Relationships

In the "one" side, add a relationship with a back reference to the "many" side:

class Department(db.Model):
    # ...
    # Key relationship code
    employees = db.relationship('Employee', backref='department', lazy='dynamic')

Many-to-One Relationships

In the "many" side, add a foreign key to the "one" side:

class Employee(db.Model):
    # ...
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))

Many-to-Many Relationships

association_table = db.Table('employee_projects',
    db.Column('employee_id', db.Integer, db.ForeignKey('employees.id')),
    db.Column('project_id', db.Integer, db.ForeignKey('projects.id'))
)

class Project(db.Model):
    # ...
    pass

class Employee(db.Model):
    # ...
    projects = db.relationship('Project', secondary=association_table,
                              backref=db.backref('employees', lazy='dynamic'),
                              lazy='dynamic')

Common Query Filters

Filter Description
filter() Adds a filter to the query, returning a new query
filter_by() Adds equality filters to the query, returning a new query
limit() Limits the query results to a specified number of items
offset() Offsets the query results, returning a new query
order_by() Orders query results by specified criteria, returning a new query
group_by() Groups query results by specified criteria, returning a new query

Common Query Execution Methods

Method Description
all() Returns all query results as a list
first() Returns the first query result or None if not found
first_or_404() Returns the first result or raises a 404 error if not found
get() Returns the record with the specified primary key or None
get_or_404() Returns the record with the specified primary key or raises a 404 error
count() Returns the number of query results
paginate() Returns a Pagination object with results in a specified range

Database Migration with Flask-Migrate

During development, database models often need modification, and the database schema must be updated accordingly. Rather than deleting tables (which would lose data), database migration frameworks can track schema changes and apply them to the database.

Flask-Migrate is an extension that integrates with Flask-Script to provide database migration commands.

Installation

pip install flask-migrate

Setting Up Migration

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)

# Database connection configuration
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://user:password@localhost:3306/my_database"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Initialize SQLAlchemy and associate with the current app
db = SQLAlchemy(app)

# Initialize migration and associate with the app
migrate = Migrate(app, db)
manager = Manager(app)
# Add db command to manager
manager.add_command('db', MigrateCommand)

# Define models
class Department(db.Model):
    __tablename__ = "departments"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    employees = db.relationship('Employee', backref='department', lazy='dynamic')

    def __repr__(self):
        return f'<Department {self.name}>'

class Employee(db.Model):
    __tablename__ = "employees"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    email = db.Column(db.String(64), default='')
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))

    def __repr__(self):
        return f'<Employee {self.name} {self.email} {self.department_id}>'

@app.route('/')
def index():
    return 'Hello World'

if __name__ == '__main__':
    manager.run()

Migration Commands

Create a migration repository:

python app.py db init

Create migration scripts:

python app.py db migrate -m 'initial migration'

Update the database:

python app.py db upgrade

View migration history:

python app.py db history

Downgrade to a specific version:

python app.py db downgrade <version_id>

Tags: Flask SQLAlchemy database ORM web development

Posted on Fri, 30 Oct 2026 16:26:01 +0000 by forums