SQLAlchemy-Utils

raw JSON →
0.42.1 verified Tue May 12 auth: no python install: verified

SQLAlchemy-Utils is a library that provides various utility functions, new data types, and helpers for SQLAlchemy. It extends SQLAlchemy's functionality by offering additional features to simplify common database tasks like managing database existence, custom column types (e.g., ChoiceType, UUIDType, EmailType), and ORM helpers. The library is actively maintained with frequent updates, typically a few minor releases per year, and is currently at version 0.42.1.

pip install sqlalchemy-utils
breaking Version 0.42.0 dropped support for Python 3.7 and 3.8. Users on these Python versions must either upgrade their Python environment or pin `sqlalchemy-utils<0.42.0` to avoid compatibility issues.
fix Upgrade Python to 3.9+ or pin `sqlalchemy-utils` version: `pip install 'sqlalchemy-utils<0.42.0'`.
breaking Version 0.42.0 dropped support for SQLAlchemy 1.3. SQLAlchemy 2.0 support was added in 0.40.0 and subsequent versions include fixes for SQLAlchemy 2.0.x compatibility. Ensure your SQLAlchemy version is 1.4 or 2.x.
fix Upgrade SQLAlchemy to 1.4.x or 2.x: `pip install 'sqlalchemy>=1.4,<3.0'`.
gotcha When using `ColorType`, be aware of a potential import name conflict if the `colour-science` package is also installed, as it shares the same import name (`colour`) as the package `sqlalchemy-utils` expects. This was fixed in 0.39.0 to avoid crashes.
fix Upgrade to `sqlalchemy-utils>=0.39.0` or avoid installing `colour-science` alongside older versions.
gotcha `create_database` and `database_exists` functions handle different database dialects (e.g., PostgreSQL, MySQL, SQLite) differently. For PostgreSQL and MySQL, they connect to a default/master database to check/create the target database, requiring appropriate credentials and server access, not just database-specific access.
fix Ensure the provided URL has credentials for a database with sufficient privileges to create new databases (e.g., `postgres` user for PostgreSQL) and that the database server is running.
gotcha A specific `AttributeError` could occur with `Sequence` defaults in `instant_defaults_listener`. This issue was resolved in version 0.42.1.
fix Upgrade to `sqlalchemy-utils>=0.42.1`.
gotcha When using SQLAlchemy with specific database backends (e.g., PostgreSQL, MySQL), the corresponding database driver (e.g., `psycopg2` for PostgreSQL, `mysqlclient` for MySQL) must be installed separately. A `ModuleNotFoundError` will occur if the required driver is missing during engine creation.
fix Install the appropriate database driver for your chosen backend, e.g., `pip install psycopg2-binary` for PostgreSQL or `pip install mysqlclient` for MySQL.
gotcha `sqlalchemy-utils` relies on SQLAlchemy for database connectivity. When connecting to a specific database (e.g., PostgreSQL, MySQL), the corresponding SQLAlchemy database driver (e.g., `psycopg2` for PostgreSQL, `pymysql` for MySQL) must be installed separately. This error indicates the required driver is missing.
fix Install the appropriate database driver for your chosen SQLAlchemy dialect. For PostgreSQL, run: `pip install psycopg2-binary`. For MySQL, run: `pip install pymysql`.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.94s 43.4M
3.10 alpine (musl) - - 0.93s 43.3M
3.10 slim (glibc) wheel 3.4s 0.70s 42M
3.10 slim (glibc) - - 0.66s 42M
3.11 alpine (musl) wheel - 1.35s 48.5M
3.11 alpine (musl) - - 1.44s 48.5M
3.11 slim (glibc) wheel 3.1s 1.18s 47M
3.11 slim (glibc) - - 1.12s 47M
3.12 alpine (musl) wheel - 1.36s 39.8M
3.12 alpine (musl) - - 1.38s 39.8M
3.12 slim (glibc) wheel 2.9s 1.28s 38M
3.12 slim (glibc) - - 1.32s 38M
3.13 alpine (musl) wheel - 1.27s 39.3M
3.13 alpine (musl) - - 1.29s 39.2M
3.13 slim (glibc) wheel 2.9s 1.21s 38M
3.13 slim (glibc) - - 1.31s 38M
3.9 alpine (musl) wheel - 0.86s 41.9M
3.9 alpine (musl) - - 0.88s 41.9M
3.9 slim (glibc) wheel 4.0s 0.83s 41M
3.9 slim (glibc) - - 0.78s 41M

This quickstart demonstrates how to use `sqlalchemy-utils` to create and manage a PostgreSQL database programmatically, define a model with a custom `ChoiceType`, and perform basic ORM operations. It utilizes `database_exists`, `create_database`, and `ChoiceType` from the utility library. Environment variables are used for database credentials for security and flexibility. To run this, ensure a PostgreSQL server is accessible and you have `psycopg2-binary` or `psycopg` installed.

import os
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy_utils import database_exists, create_database, drop_database, ChoiceType

# --- Database Setup ---
DB_USER = os.environ.get('DB_USER', 'testuser')
DB_PASS = os.environ.get('DB_PASS', 'testpass')
DB_HOST = os.environ.get('DB_HOST', 'localhost')
DB_NAME = os.environ.get('DB_NAME', 'test_db')
DATABASE_URL = f"postgresql://{DB_USER}:{DB_PASS}@{DB_HOST}/{DB_NAME}"

engine = create_engine(DATABASE_URL)

# Create database if it doesn't exist
if not database_exists(engine.url):
    create_database(engine.url)
    print(f"Database '{DB_NAME}' created.")
else:
    print(f"Database '{DB_NAME}' already exists.")

Session = sessionmaker(bind=engine)
Base = declarative_base()

# --- Define a Model with ChoiceType ---
class TaskPriority:
    LOW = 'low'
    MEDIUM = 'medium'
    HIGH = 'high'

class Task(Base):
    __tablename__ = 'tasks'

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    priority = Column(ChoiceType(TaskPriority, impl=String(10)))

    def __repr__(self):
        return f"<Task(id={self.id}, name='{self.name}', priority='{self.priority}')>"

# --- ORM Operations ---
Base.metadata.create_all(engine) # Create tables

session = Session()

# Add tasks
task1 = Task(name="Write documentation", priority=TaskPriority.HIGH)
task2 = Task(name="Review code", priority=TaskPriority.MEDIUM)
task3 = Task(name="Deploy update", priority=TaskPriority.LOW)

session.add_all([task1, task2, task3])
session.commit()

# Query tasks
print("\nAll tasks:")
for task in session.query(Task).all():
    print(task)

# Clean up (optional: uncomment to drop the database)
# session.close()
# drop_database(engine.url)
# print(f"Database '{DB_NAME}' dropped.")