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.0.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.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: flex_alchemy-0.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 dc7d01ab5d148f94e17b5dae81ecd5f55b16c7c40bb1bf0af91195d994f2414b
MD5 f12bac55c095b6b1f7e8fe7f92fc038e
BLAKE2b-256 c825e8fbcb5132a7faed23a682a0d2a5d1dca51afc32bfae86ee29bcb6604348

See more details on using hashes here.

File details

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

File metadata

  • Download URL: flex_alchemy-0.1.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 179a7bb3022cf43f5ac3f7935e6178198fa965826b5169a37f134391eaafb94a
MD5 1ef3940a140679bcb994f974aa09aecf
BLAKE2b-256 ca013ca94cb91fc7ce3433c4727981177420cab1c9216ede937dce1578e695d5

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