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.2.tar.gz (26.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.2-py3-none-any.whl (28.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: better_crud-0.2.2.tar.gz
  • Upload date:
  • Size: 26.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.2.tar.gz
Algorithm Hash digest
SHA256 5f68db7f73521fae1a641bef675deed983b58de1bd7997b2e991b664e11f5bd6
MD5 2205ba3ebadda3ba91b4795aa56186f3
BLAKE2b-256 89c09b5bc48d10aebabd4a7fdcee76ad1afef9ad42a687659e7d84279843c48f

See more details on using hashes here.

Provenance

The following attestation bundles were made for better_crud-0.2.2.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.2-py3-none-any.whl.

File metadata

  • Download URL: better_crud-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 28.0 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8b3186d4f7ab6ccf9d7cfe9f2c310cb55f2a7f63d95ec7566664b1137f2f4f1c
MD5 912b2535899ec81ab8310fd6461ee11a
BLAKE2b-256 7a4768cb2166104ab63c255473569b61efaf8e5d0a5c7d90d5b4cd404483b5f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for better_crud-0.2.2-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