Skip to main content

Common CRUD operations for SQLAlchemy and FastAPI

Project description

Common CRUD

A lightweight, flexible library for common CRUD (Create, Read, Update, Delete) operations with SQLAlchemy and FastAPI.

Python 3.11+ SQLAlchemy 2.0+ License: MIT

Overview

Common CRUD provides a clean, reusable base class (BaseCRUD) that handles standard database operations for SQLAlchemy models. It's designed to:

  • Reduce boilerplate code for common database operations
  • Provide consistent error handling and logging
  • Support both simple and advanced filtering options
  • Work seamlessly with SQLAlchemy's async functionality

Installation

pip install common-crud

Or with Poetry:

poetry add common-crud

Dependencies

  • Python 3.11+
  • SQLAlchemy 2.0+

Usage

Basic Setup

Create a CRUD class for your SQLAlchemy model:

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from common_crud import BaseCRUD

# Define your SQLAlchemy model
Base = declarative_base()

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String, unique=True)

# Create a CRUD class for your model
class UserCRUD(BaseCRUD):
    model = User
    # Optional: Define fields that should use ILIKE for case-insensitive search
    filter_fields = {"name": "ilike", "email": "ilike"}

Basic Operations

import asyncio
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker

# Create engine and session
engine = create_async_engine("sqlite+aiosqlite:///database.db")
async_session = async_sessionmaker(engine, expire_on_commit=False)

async def main():
    async with async_session() as session:
        # Create
        new_user = await UserCRUD.add(
            session=session, 
            name="John Doe",
            email="john@example.com"
        )
        print(f"Added user: {new_user.id}")
        
        # Read by ID
        user = await UserCRUD.find_one_or_none_by_id(
            session=session,
            data_id=new_user.id
        )
        print(f"Found user: {user.name}")
        
        # Read with filter
        users = await UserCRUD.find_all(
            session=session, 
            name="John"  # Will use ILIKE since it's in filter_fields
        )
        print(f"Found {len(users)} users")
        
        # Update
        rows_updated = await UserCRUD.update(
            session=session,
            filter_by={"id": new_user.id},
            name="John Smith"
        )
        print(f"Updated {rows_updated} rows")
        
        # Delete
        rows_deleted = await UserCRUD.delete(
            session=session,
            id=new_user.id
        )
        print(f"Deleted {rows_deleted} rows")

# Run the async function
asyncio.run(main())

Advanced Features

Time Range Filtering

Filter records based on a date/time field:

# Find all records created between two dates
records = await MyCRUD.find_all_in_time_range(
    session=session,
    start_time=datetime(2023, 1, 1),
    end_time=datetime(2023, 12, 31),
    param="created_at"  # Default field name
)

Bulk Insert

Efficiently insert multiple records:

rows_inserted = await UserCRUD.bulk_insert(
    session=session,
    data=[
        {"name": "User 1", "email": "user1@example.com"},
        {"name": "User 2", "email": "user2@example.com"},
        {"name": "User 3", "email": "user3@example.com"}
    ]
)

Error Handling

The library provides specialized exceptions:

from common_crud.exceptions import CRUDError, ModelNotSetError, InvalidFilterError, DatabaseError

try:
    await UserCRUD.update(session=session, filter_by={}, name="New Name")
except InvalidFilterError:
    print("Need to provide filter criteria for update")
except DatabaseError as e:
    print(f"Database error: {e}")
except CRUDError as e:
    print(f"Generic error: {e}")

FastAPI Integration

Works seamlessly with FastAPI:

from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_session  # Your session dependency
from models import User, UserCRUD
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    email: str

class UserResponse(BaseModel):
    id: int
    name: str
    email: str
    
    class Config:
        orm_mode = True

@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate, session: AsyncSession = Depends(get_session)):
    try:
        db_user = await UserCRUD.add(session=session, **user.dict())
        return db_user
    except DatabaseError as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int, session: AsyncSession = Depends(get_session)):
    user = await UserCRUD.find_one_or_none_by_id(session=session, data_id=user_id)
    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return user

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

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

common_crud-0.1.2.tar.gz (4.8 kB view details)

Uploaded Source

Built Distribution

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

common_crud-0.1.2-py3-none-any.whl (5.3 kB view details)

Uploaded Python 3

File details

Details for the file common_crud-0.1.2.tar.gz.

File metadata

  • Download URL: common_crud-0.1.2.tar.gz
  • Upload date:
  • Size: 4.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.11.9 Windows/10

File hashes

Hashes for common_crud-0.1.2.tar.gz
Algorithm Hash digest
SHA256 ca5703085a5eca2d4eb6ec3bd8d0ef3a4c4831c3c1f8b0e64b7d27c554072972
MD5 1d1e2ddf24f835be049f1d355aac641b
BLAKE2b-256 f25af70494114d8dce947afa19f39bbd8032063cb1f976bd2516d242f5880430

See more details on using hashes here.

File details

Details for the file common_crud-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: common_crud-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 5.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.11.9 Windows/10

File hashes

Hashes for common_crud-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4699d1a001ba18a0a8924dffb914673ae92cdb289142f41c68b26d1158e883dc
MD5 05a8bb5474d6b1aa6df80f24064b579e
BLAKE2b-256 7f61c78374505eef76bef031e19136975052d547b8c720612dc8f28ba389e41b

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