Skip to main content

BetterCRUD

A better CRUD library for FastAPI.
FastAPI CRUD routing library based on class view, you can control everything

Tests PyPi Version Supported Python Versions


Documentation: https://bigrivi.github.io/better_crud/

Source Code: https://github.com/bigrivi/better_crud


BetterCRUD is a library that can quickly generate CRUD routes for you without any intrusion to your code. You can still control everything. When you are troubled by a large number of repeated CRUD routes, I believe it can help you, saving you a lot of time and allowing you to focus more on business logic.

BetterCRUD is reliable, fully tested, and used in project production environments.

BetterCRUD is a way to dynamically generate routes by combining your model with the crud decorator,I believe bring you a different development experience

You only need to configure some crud options and define your model to produce powerful CRUD functions

@crud(
    router,
    dto={
        "create": PetCreate,
        "update": PetUpdate
    },
    serialize={
        "base": PetPublic,
    },
    **other_options
)
class PetController():
    service: PetService = Depends(PetService)

Requirements

  • Python: Version 3.9 or newer.
  • FastAPI: BetterCRUD is built to work with FastAPI, so having FastAPI in your project is essential.
  • SQLAlchemy: Version 2.0.30 or newer. BetterCRUD uses SQLAlchemy for database operations.
  • Pydantic: Version 2.7.3 or newer. BetterCRUD leverages Pydantic models for data validation and serialization.

Installation

pip install better-crud

Features

  • Fully Async, Synchronization is not supported
  • Less boilerplate code
  • Configuring static type support
  • More flexible custom configuration,Less invasive
  • Compatible with both class views and functional views
  • Rich filter, pagination, and sorting support
  • Automated relationship support, query and storage
  • Extensible custom backend

Why BetterCRUD over fastapi-crudrouter?

The long-time de-facto CRUD library for FastAPI, fastapi-crudrouter, has been unmaintained since Nov 2023. BetterCRUD is actively maintained and provides a strict superset of its features:

Feature BetterCRUD fastapi-crudrouter
Actively maintained (2026) ❌ (stalled since 2023)
FastAPI 0.141+ support
SQLAlchemy 2.0 async
Rich filter operators ($eq $cont $notany $in …)
Nested relationship queries & joins
Many-to-many relationship storage
Lifecycle hooks (on_after_create/update/...)
ACL / permission guards
Pagination
Class views & function views
Test coverage 99%

💡 Migrating from fastapi-crudrouter? The route layout is nearly identical (GET/POST /resource, GET/PUT/DELETE /resource/{id}), so switching is mostly a drop-in change. A dedicated migration guide is on the roadmap.

Default Routes

Route Method Description
/resource GET Get Many
/resource/{id} GET Get One
/resource POST Create One
/resource/bulk POST Create Many
/resource/{id} PUT Update One
/resource/{ids}/bulk PUT Update Many
/resource/{ids} DELETE Delete Many

Minimal Example

Prerequisites,Prepare our db, Only asynchronous mode is supported,aiomysql or aiosqlite db.py

from sqlalchemy.orm import DeclarativeBase, declared_attr
from typing import AsyncGenerator
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
DATABASE_URL = "sqlite+aiosqlite:///crud.db"

class MappedBase(DeclarativeBase):
    @declared_attr.directive
    def __tablename__(cls) -> str:
        return cls.__name__.lower()


class Base(MappedBase):
    __abstract__ = True


engine = create_async_engine(
    DATABASE_URL,
    echo=False,
    poolclass=NullPool
)

SessionLocal = sessionmaker(
    autocommit=False,
    autoflush=False,
    bind=engine,
    class_=AsyncSession,
    expire_on_commit=False,
)


async def get_session() -> AsyncGenerator[AsyncSession, None]:
    async with SessionLocal() as session:
        yield session


async def init_db():
    async with engine.begin() as conn:
        await conn.run_sync(MappedBase.metadata.create_all)

First Define Your Model And Schema

model.py

from sqlalchemy import String, Integer, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column
from .db import Base


class Pet(Base):
    __tablename__ = "pet"
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(100))
    description: Mapped[str] = mapped_column(String(100))

schema.py

from typing import Optional, List
from pydantic import BaseModel


class PetBase(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None


class PetPublic(PetBase):
    id: int


class PetCreate(PetBase):
    pass


class PetUpdate(PetBase):
    pass

Next we need to create a service:

service.py

from better_crud.service.sqlalchemy import SqlalchemyCrudService
from .model import Pet


class PetService(SqlalchemyCrudService[Pet]):
    def __init__(self):
        super().__init__(Pet)

Next we need to define the controller and decorate it with the crud decorator Sure the controller is just a normal class,The crud decorator gives it super powers controller.py

from fastapi import APIRouter, Depends
from better_crud import crud
from .schema import PetCreate, PetUpdate, PetPublic
from .service import PetService

pet_router = APIRouter()


@crud(
    pet_router,
    dto={
        "create": PetCreate,
        "update": PetUpdate
    },
    serialize={
        "base": PetPublic,
    }
)
class PetController():
    service: PetService = Depends(PetService)

Next we can register router to the fastapi routing system

main.py

from better_crud import BetterCrudGlobalConfig
from fastapi import FastAPI
from contextlib import asynccontextmanager
from .db import get_session, init_db

BetterCrudGlobalConfig.init(
    backend_config={
        "sqlalchemy": {
            "db_session": get_session
        }
    }
)


@asynccontextmanager
async def lifespan(_: FastAPI):
    await init_db()
    # Shutdown
    yield

app = FastAPI(lifespan=lifespan)


def register_router():
    from app.controller import pet_router
    app.include_router(pet_router, prefix="/pet")


register_router()

Congratulations, your first CRUD route has been created!

OpenAPI Route Overview

Author

👤 bigrivi

🤝 Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Credits

This project draws inspiration from the following frameworks:

UseCases

BetterCrud was used in the following projects:

License

MIT

Download files

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

Source Distribution

better_crud-0.2.1.tar.gz (25.1 kB view details)

Uploaded Source

Built Distribution

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

better_crud-0.2.1-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file better_crud-0.2.1.tar.gz.

File metadata

  • Download URL: better_crud-0.2.1.tar.gz
  • Upload date:
  • Size: 25.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for better_crud-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8a2df649ac8c362d0d2a7c43d00335c514cd8a03ef5f4602962f07d59e0ac163
MD5 bfa60f1bc6f6d943c8400a17ee1da2e7
BLAKE2b-256 f60d536710ea9c0607d6c0b06b08a42034681177e6ceb2c407601f6528638fc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for better_crud-0.2.1.tar.gz:

Publisher: publish.yml on bigrivi/better_crud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file better_crud-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: better_crud-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 27.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for better_crud-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e5585d8a4e880d28b0f597eca9661256126fe284c74943e1b9c9dd0330a4e2a7
MD5 ca231fb23ddb9405ac4e2b09cfd15d2e
BLAKE2b-256 4fb2c225f6af8933a5e7271db89bcfec111304c8fb2b75e85944c25b6b1df8ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for better_crud-0.2.1-py3-none-any.whl:

Publisher: publish.yml on bigrivi/better_crud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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