Ready-made FastAPI abstractions: repository, unit of work, service etc.
Project description
FastAPI Abstractions
Ready-made FastAPI abstractions: repository, unit of work, service etc.
Features
- Focus on business logic: No need to write boilerplate code.
- Scalable: You can use the provided abstractions and easily extend them.
- Portable: Works with any database supported by SQLAlchemy.
- Intuitive: Great editor support. Completion everywhere. Less time debugging.
- Easy: Designed to be easy to use and learn. Less time reading docs.
- Asynchronous: Built-in support for async/await.
- Use anywhere: Use it with FastAPI, Aiogram, or any other framework (best with FastAPI).
Requirements
FastAPI Abstractions stands on the shoulders of giants:
Installation
pip install fastabc
Concepts
1. Models
from datetime import datetime
from sqlalchemy import Identity
from sqlalchemy.orm import Mapped, mapped_column
from fastabc import DeclarativeBase, AlchemyEntity
from fastabc.alchemy import SoftDeletable, HasID, HasTimestamp
# Classic way
class User(DeclarativeBase):
__tablename__ = "users"
id: Mapped[int] = mapped_column(Identity(), primary_key=True)
email: Mapped[str] = mapped_column(unique=True, index=True)
password: Mapped[str]
created_at: Mapped[datetime] = mapped_column(default=datetime.now)
updated_at: Mapped[datetime] = mapped_column(
default=datetime.now, onupdate=datetime.now
)
# Using AlchemyEntity
class UserAlchemyEntity(AlchemyEntity):
__tablename__ = "users"
email: Mapped[str] = mapped_column(unique=True, index=True)
password: Mapped[str]
# These columns will be added automatically
# id: Mapped[int] = mapped_column(Identity(), primary_key=True)
# created_at: Mapped[datetime] = mapped_column(default=datetime.now)
# updated_at: Mapped[datetime] = mapped_column(
# default=datetime.now, onupdate=datetime.now
# )
# Using mixins
class UserMixins(HasID, HasTimestamp, SoftDeletable):
__tablename__ = "users"
email: Mapped[str] = mapped_column(unique=True, index=True)
password: Mapped[str]
# These columns will be added automatically
# id: Mapped[int]
# created_at: Mapped[datetime] = mapped_column(default=datetime.now)
# updated_at: Mapped[datetime] = mapped_column(
# default=datetime.now, onupdate=datetime.now
# )
# deleted_at: Mapped[datetime | None] = None
2. Repositories
from fastabc import AlchemyRepository
from .models import User
class UserRepository(AlchemyRepository[User]):
model_type = User
3. Unit of Work
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from fastabc import AlchemyUOW
from .repositories import UserRepository
class UOW(AlchemyUOW):
users: UserRepository
async def on_open(self) -> None:
self.users = UserRepository(self.session)
async_engine = create_async_engine("sqlite+aiosqlite:///memory")
async_session = async_sessionmaker(async_engine)
uow = UOW(async_session)
4. Services
from fastabc import AlchemyService
from .models import User
from .uow import UOW
class UserService(AlchemyService):
uow: UOW
async def create(self, email: str, password: str) -> User:
user = User(email=email, password=password)
self.uow.users.add(user)
await self.uow.commit()
return user
async def get(self, user_id: int) -> User | None:
return await self.uow.users.get(user_id)
async def get_by_email(self, email: str) -> User | None:
return await self.uow.users.get_by_where(where=[User.email == email])
async def create_many(self, users: list[User]) -> list[User]:
await self.uow.users.insert(*users)
await self.uow.commit()
return users
async def get_by_domain(self, domain: str) -> list[User]:
return await self.uow.users.get_many(where=[User.email.like(f"%@{domain}")])
# And more...
5. Use Cases
from faker import Faker
from .models import User
from .service import UserService
from .uow import uow
fake = Faker()
def get_users(domains: list[str], number: int = 10) -> list[User]:
users = [User(email=fake.email(domain=domain), password=fake.password()) for _ in range(number) for domain in
domains]
return users
async def main():
async with uow:
service = UserService(uow)
user = await service.create("user@example.com", "qwerty12345")
print(user)
user = await service.get(user.id)
print(user)
user = await service.get_by_email("user@example.com")
print(user)
users = get_users(["gmail.com", "yahoo.com"])
await service.create_many(*users)
users = await service.get_by_domain("gmail.com")
print(users)
Made with love ❤️
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
fastabc-0.1.8.tar.gz
(11.1 kB
view details)
Built Distribution
fastabc-0.1.8-py3-none-any.whl
(16.7 kB
view details)
File details
Details for the file fastabc-0.1.8.tar.gz
.
File metadata
- Download URL: fastabc-0.1.8.tar.gz
- Upload date:
- Size: 11.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.3 Windows/11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9db255b5d378c5c660ed7152c0912f618fb08066b8fb6302dbc6259d2ee7d6f0 |
|
MD5 | f0d0e6c595c24cd6220db15436558d87 |
|
BLAKE2b-256 | 68460e67e7a5df91af0c6cb62ae4aa9dabd4908f386da989765f2276513739c5 |
File details
Details for the file fastabc-0.1.8-py3-none-any.whl
.
File metadata
- Download URL: fastabc-0.1.8-py3-none-any.whl
- Upload date:
- Size: 16.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.3 Windows/11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7b13f6549877b4737fa8519347272fbc834b11ca5292e4f7c9786811c2b51446 |
|
MD5 | 7f64c5bed3051da1e235bf1b98999647 |
|
BLAKE2b-256 | 21cf66715b26e424cac90de6dd425cad824d2e03f3a773ccbb2a257c4cac750d |