Skip to main content

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

Metadata

Release files for flex-alchemy 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flex-alchemy 0.1.1
File Size Uploaded Provenance Actions
flex_alchemy-0.1.1.tar.gz 5.9 kB Without provenance Details for flex_alchemy-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for flex-alchemy 0.1.1
File Interpreter ABI Platform Actions
flex_alchemy-0.1.1-py3-none-any.whl Python 3 none any Details for flex_alchemy-0.1.1-py3-none-any.whl

Total release size: 15.9 kB

Release files / flex_alchemy-0.1.1.tar.gz

Download URL flex_alchemy-0.1.1.tar.gz
Size 5.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a74c6be3393655d600735806fd707787876ff6f62ff9a54687a7c8f4a8138415
BLAKE2b-256 checksum
How to use checksums
6672cfbade0dd1279b113768f7b4318a56635e74ab37973a0433b23e07834ffa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.1 CPython/3.10.11 Darwin/24.1.0

Release files / flex_alchemy-0.1.1-py3-none-any.whl

Download URL flex_alchemy-0.1.1-py3-none-any.whl
Size 10.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eec8b77b8dfce09c9377a8111e1de1e7ad3c712440804c271e2b48423fb4d912
BLAKE2b-256 checksum
How to use checksums
a947774548e7a06fd23dbe2640127f4b761cef1c60626f5abdf19b587d6a902f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.1 CPython/3.10.11 Darwin/24.1.0

Security for flex-alchemy 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page