gitignore

main
Сергей Ванюшкин 2024-03-11 18:07:01 +00:00
parent 83bea97f41
commit fb7e64f738
22 changed files with 114 additions and 58 deletions

View File

@ -60,7 +60,7 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne
# are written from script.py.mako # are written from script.py.mako
# output_encoding = utf-8 # output_encoding = utf-8
sqlalchemy.url = postgresql://demo_user:user_pass@db:5432/serviceman_db sqlalchemy.url = postgresql://demo_user:user_pass@localhost:5432/serviceman_db
[post_write_hooks] [post_write_hooks]

View File

@ -1,6 +1,6 @@
from fastapi import FastAPI from fastapi import FastAPI
from api.router.user import router as user_router from api.routers.user import router as user_router
def create_app() -> FastAPI: def create_app() -> FastAPI:

View File

@ -3,7 +3,7 @@ import os
import yaml # type: ignore import yaml # type: ignore
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
with open(os.getenv("CONFIG_PATH", "")) as f: with open(os.getenv("CONFIG_PATH", "./config/api_config.yml")) as f:
config_data: dict = yaml.safe_load(f) config_data: dict = yaml.safe_load(f)
if os.getenv("INDOCKER"): if os.getenv("INDOCKER"):

View File

@ -1,12 +1,13 @@
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.ext.asyncio import (AsyncSession, async_sessionmaker,
create_async_engine)
from api.config import get_settings from api.config import get_settings
from api.service.user import UserService from api.services.user import UserService
from api.uow.uow_base import UnitOfWork from api.uow.uow_base import UnitOfWork
async_engine = create_async_engine( async_engine = create_async_engine(
url=get_settings().get_db_url, url=get_settings().get_db_url,
echo=True, echo=False,
) )
async_session_factory = async_sessionmaker( async_session_factory = async_sessionmaker(

View File

@ -1,7 +1,7 @@
from .base import Base from .base_model import Base
from .user import User from .user_model import UserModel
__all__ = ( __all__ = (
"Base", "Base",
"User", "UserModel",
) )

View File

@ -5,6 +5,8 @@ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase): class Base(DeclarativeBase):
__abstract__ = True
id: Mapped[uuid.UUID] = mapped_column( id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), UUID(as_uuid=True),
primary_key=True, primary_key=True,

View File

@ -1,12 +1,12 @@
from sqlalchemy import Boolean, Column, String from sqlalchemy import Boolean, Column, String
from sqlalchemy.orm import Mapped from sqlalchemy.orm import Mapped
from api.schemas.user_schema import UserSchema from api.schemas import UserReadDTO
from .base import Base from . import Base
class User(Base): class UserModel(Base):
__tablename__ = "users" __tablename__ = "users"
name: Mapped[str] name: Mapped[str]
@ -22,8 +22,8 @@ class User(Base):
f"is_active={self.is_active})>" f"is_active={self.is_active})>"
) )
def to_read_model(self) -> UserSchema: def to_read_model(self) -> UserReadDTO:
return UserSchema( return UserReadDTO(
id=self.id, id=self.id,
name=self.name, name=self.name,
) )

View File

@ -0,0 +1,7 @@
from .repository import AbstractRepository
from .user import UserRepository
__all__ = (
"AbstractRepository",
"UserRepository",
)

View File

@ -0,0 +1,23 @@
from abc import ABC, abstractmethod
class AbstractRepository(ABC):
@abstractmethod
async def add_one(self, data: dict):
raise NotImplementedError()
@abstractmethod
async def find_all(self):
raise NotImplementedError()
@abstractmethod
async def find_one(self, filter: dict):
raise NotImplementedError()
@abstractmethod
async def update_one(self, filter: dict, data: dict):
raise NotImplementedError()
@abstractmethod
async def delete_one(self, filter: dict):
raise NotImplementedError()

30
api/repositories/user.py Normal file
View File

@ -0,0 +1,30 @@
from sqlalchemy import insert, select
from sqlalchemy.ext.asyncio.session import AsyncSession
from api.models import UserModel
from api.repositories import AbstractRepository
class UserRepository(AbstractRepository):
def __init__(self, session: AsyncSession):
self.session = session
async def add_one(self, data: dict):
stmt = insert(UserModel).values(**data)
res = await self.session.execute(stmt)
return res.scalar_one()
async def find_all(self):
stmt = select(UserModel)
res = await self.session.execute(stmt)
res = [row[0].to_read_model() for row in res.all()]
return res
async def find_one(self, filter: dict):
return
async def update_one(self, filter: dict, data: dict):
return
async def delete_one(self, filter: dict):
return

View File

@ -1,6 +0,0 @@
import api.models as models
from api.uow.repository import SQLAlchemyRepository
class UserRepository(SQLAlchemyRepository):
model = models.User

View File

View File

@ -1,16 +1,16 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from api.di import get_user_service from api.di import get_user_service
from api.schemas.user_schema import UserSchema from api.schemas import UserReadDTO
from api.service.user import UserService from api.services import UserService
router = APIRouter() router = APIRouter()
@router.get("/users", response_model=list[UserSchema]) @router.get("/users", response_model=list[UserReadDTO])
async def get_user_list( async def get_user_list(
user_service: UserService = Depends(get_user_service), user_service: UserService = Depends(get_user_service),
) -> list[UserSchema]: ) -> list[UserReadDTO]:
return await user_service.get_all_users() return await user_service.get_all_users()

9
api/schemas/__init__.py Normal file
View File

@ -0,0 +1,9 @@
from .base_schema import ReadDTO, WriteDTO
from .user_schema import UserReadDTO, UserWriteDTO
__all__ = (
"WriteDTO",
"ReadDTO",
"UserWriteDTO",
"UserReadDTO",
)

View File

@ -0,0 +1,13 @@
from uuid import UUID
from pydantic import BaseModel
class WriteDTO(BaseModel):
class Config:
from_attributes = True
class ReadDTO(WriteDTO):
id: UUID

View File

@ -1,11 +1,9 @@
from uuid import UUID from . import ReadDTO, WriteDTO
from pydantic import BaseModel
class UserSchema(BaseModel): class UserWriteDTO(WriteDTO):
id: UUID
name: str name: str
class Config:
from_attributes = True class UserReadDTO(ReadDTO, UserWriteDTO):
pass

3
api/services/__init__.py Normal file
View File

@ -0,0 +1,3 @@
from .user import UserService
__all__ = ("UserService",)

View File

@ -1,26 +0,0 @@
from typing import Generic, TypeVar
from sqlalchemy import insert, select
from sqlalchemy.ext.asyncio import AsyncSession
import api.models as models
ModelType = TypeVar("ModelType", bound=models.Base)
class SQLAlchemyRepository(Generic[ModelType]):
model: type[ModelType]
def __init__(self, session: AsyncSession):
self.session = session
async def add_one(self, data: dict) -> ModelType:
stmt = insert(self.model).values(**data)
res = await self.session.execute(stmt)
return res.scalar_one()
async def find_all(self) -> list[ModelType]:
stmt = select(self.model)
res = await self.session.execute(stmt)
res = [row[0].to_read_model() for row in res.all()]
return res

View File

@ -1,4 +1,4 @@
from api.repository.user import UserRepository from api.repositories import UserRepository
class UnitOfWork: class UnitOfWork:
@ -9,6 +9,8 @@ class UnitOfWork:
self.session = self.session_factory() self.session = self.session_factory()
self.users = UserRepository(self.session) self.users = UserRepository(self.session)
print("session id:", id(self.session))
print("UoW obj id:", id(self))
async def __aexit__(self, *args): async def __aexit__(self, *args):
await self.session.rollback() await self.session.rollback()