Skip to main content

SQLAlchemy with Active Record - a fluent query builder and ActiveRecord implementation for SQLAlchemy

Project description

Flex Alchemy

Use SQLAlchemy with Active Record pattern.

Installation

pip install flex-alchemy

Quick Start

  1. Declare Models and inherit ActiveRecord

    # models.py
    from sqlalchemy.orm import DeclarativeBase
    from sqlalchemy import String, BigInteger, Boolean
    from sqlalchemy.orm import Mapped, mapped_column
    from flex_alchemy import ActiveRecord
    
    class Base(DeclarativeBase, ActiveRecord):
        pass
    
    class User(Base):
        __tablename__ = "users"
    
        id: Mapped[int] = mapped_column(BigInteger(), primary_key=True)
        email: Mapped[str] = mapped_column(String(), unique=True)
        password: Mapped[str] = mapped_column(String())
        name: Mapped[str] = mapped_column(String(50))
        enable: Mapped[bool] = mapped_column(Boolean(), default=True)
    
  2. Create SQLAlchemy Engine, and assign to session handler in ActiveRecord

    # database.py
    from sqlalchemy import create_engine
    from models import Base
    
    engine = create_engine("sqlite:///:memory:")
    
    Base.make_session(engine)
    
  3. Start using model to operate database!

    from models import User
    
    users = User.all()
    # [User(id=1), User(id=2), ...]
    
  4. Release session resource after use

    from models import Base
    
    Base.teardown_session()
    

Usage

Create Records

# Option #1: Use class method `create`
user = User.create(
    name="John Doe",
    email="john.doe@example.com",
    password="secure_password"
)

# Option #2: Create model instance and call `save` method
user = User(
    name="Jane Doe",
    email="jane.doe@example.com",
    password="another_password"
)
user.save()

Query Records

# find a record by primary key
user = User.find(1)

# find all records
all_users = User.all()

# find a record with specific columns
row = User.select(User.id, User.name, User.email).execute().first()

# find records with conditions
active_users = User.where(User.enable.is_(True)).execute().scalars().all()

Update Records

# find a record and update it by calling `save` method
user = User.find(1)
user.name = "New Name"
user.save()

# Update multiple records with conditions
User.update(updated_at=datetime.now()).where(User.enalbe.is_(True)).execute()

Delete Records

# delete a record by calling `delete` method
user = User.find(1)
user.delete()

# delete multiple records
User.destroy().where(User.enable.is_(False)).execute()

Examples

Use in FastAPI

from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from app.models import Base, User

engine = create_engine("postgresql://user:password@localhost/dbname")

@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    Make scoped session with engine when FastAPI start
    """
    Base.make_session(engine)
    yield

def close_session():
    """
    cleanup scoped session after each request
    """
    yield
    Base.teardown_session()


app = FastAPI(
    title="MyApp",
    lifespan=lifespan,
    dependencies=[Depends(close_session)],
)

@app.get("/users")
def index():
    """get all users"""
    return User.all()

@app.get("/users/{id_}")
def show(id_: int):
    """get user by id"""
    return User.find(id_)

@app.post("/users")
def create(user_data: dict):
    """create a new user"""
    return User.create(user_data)

Others

Use Session instead of Scoped Session

flex-alchemy provides a way to use Session instead of ScopedSession by pass a Session instance to execute method.

from sqlalchemy import create_engine
from sqlalchemy.orm import Session

engine = create_engine("sqlite:///:memory:")

with Session(engine) as session:
    # find all users
    User.all(session=session)

    # find a user by primary key
    User.find(1, session=session)

    # create a new user
    User.create({
        "name": "New User",
        "email": "example@mail.com"
        "password": "password"
    }, session=session)

    user = User(
        name="New User",
        email="example@mail.com",
        password="password"
    )
    user.save(session=session)

    User.where(User.enable.is_(True)).execute(session=session).scalars().all()

    ... etc

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flex_alchemy-0.1.1.tar.gz (5.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flex_alchemy-0.1.1-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file flex_alchemy-0.1.1.tar.gz.

File metadata

  • Download URL: flex_alchemy-0.1.1.tar.gz
  • Upload date:
  • Size: 5.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.1 CPython/3.10.11 Darwin/24.1.0

File hashes

Hashes for flex_alchemy-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a74c6be3393655d600735806fd707787876ff6f62ff9a54687a7c8f4a8138415
MD5 e9fb6e7d895f6a2e948abafb9c1ea23b
BLAKE2b-256 6672cfbade0dd1279b113768f7b4318a56635e74ab37973a0433b23e07834ffa

See more details on using hashes here.

File details

Details for the file flex_alchemy-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: flex_alchemy-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.1 CPython/3.10.11 Darwin/24.1.0

File hashes

Hashes for flex_alchemy-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 eec8b77b8dfce09c9377a8111e1de1e7ad3c712440804c271e2b48423fb4d912
MD5 12a4301eeda74d4546d0b6a61e43bfd6
BLAKE2b-256 a947774548e7a06fd23dbe2640127f4b761cef1c60626f5abdf19b587d6a902f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page