https://github.com/bigrivi/better_crud
Better crud for fastapi, without constraints
https://github.com/bigrivi/better_crud
crud-generator curd fastapi library pydanic python restful-api
Last synced: 12 months ago
JSON representation
Better crud for fastapi, without constraints
- Host: GitHub
- URL: https://github.com/bigrivi/better_crud
- Owner: bigrivi
- License: mit
- Created: 2024-07-01T23:56:17.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-06-16T05:14:45.000Z (about 1 year ago)
- Last Synced: 2025-06-16T06:23:55.869Z (about 1 year ago)
- Topics: crud-generator, curd, fastapi, library, pydanic, python, restful-api
- Language: Python
- Homepage: https://bigrivi.github.io/better_crud/
- Size: 1.73 MB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
BetterCRUD
A better CRUD library for FastAPI.
FastAPI CRUD routing library based on class view, you can control everything
---
**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
```python
@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
```bash
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
## 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**
```python
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**
```python
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**
```python
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**
```python
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**
```python
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**
```python
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!

## Author
👤 **bigrivi**
* GitHub: [bigrivi](https://github.com/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:
- [nestjsx-crud](https://github.com/nestjsx/crud)
## UseCases
BetterCrud was used in the following projects:
- [black-panther](https://github.com/bigrivi/black-panther)
## License
[MIT](LICENSE)