wip: crud refactor

This commit is contained in:
grillazz 2025-08-23 17:53:18 +02:00
parent 93f2e66bd0
commit d722504e55
6 changed files with 30 additions and 31 deletions

View File

@ -116,5 +116,5 @@ async def update_stuff(
db_session: AsyncSession = Depends(get_db), db_session: AsyncSession = Depends(get_db),
): ):
stuff = await Stuff.find(db_session, name) stuff = await Stuff.find(db_session, name)
await stuff.update(db_session, **payload.model_dump()) await stuff.update(**payload.model_dump())
return stuff return stuff

View File

@ -28,6 +28,7 @@ async def get_db() -> AsyncGenerator:
# logger.debug(f"ASYNC Pool: {engine.pool.status()}") # logger.debug(f"ASYNC Pool: {engine.pool.status()}")
try: try:
yield session yield session
await session.commit()
except Exception as e: except Exception as e:
await logger.aerror(f"Error getting database session: {e}") await logger.aerror(f"Error getting database session: {e}")
raise raise

View File

@ -3,9 +3,10 @@ from pathlib import Path
import asyncpg import asyncpg
from fastapi import Depends, FastAPI, Request from fastapi import Depends, FastAPI, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from rotoger import AppStructLogger from rotoger import AppStructLogger
from sqlalchemy.exc import SQLAlchemyError
from app.api.health import router as health_router from app.api.health import router as health_router
from app.api.ml import router as ml_router from app.api.ml import router as ml_router
@ -61,6 +62,19 @@ def create_app() -> FastAPI:
dependencies=[Depends(AuthBearer())], dependencies=[Depends(AuthBearer())],
) )
@app.exception_handler(SQLAlchemyError)
async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
await logger.aerror(
"A database error occurred",
sql_error=repr(exc),
request_url=request.url.path,
request_body=request.body,
)
return JSONResponse(
status_code=500,
content={"message": "A database error occurred. Please try again later."},
)
@app.get("/index", response_class=HTMLResponse) @app.get("/index", response_class=HTMLResponse)
def get_index(request: Request): def get_index(request: Request):
return templates.TemplateResponse("index.html", {"request": request}) return templates.TemplateResponse("index.html", {"request": request})

View File

@ -20,64 +20,46 @@ class Base(DeclarativeBase):
return self.__name__.lower() return self.__name__.lower()
async def save(self, db_session: AsyncSession): async def save(self, db_session: AsyncSession):
"""
:param db_session:
:return:
"""
try: try:
db_session.add(self) db_session.add(self)
await db_session.commit() await db_session.flush()
await db_session.refresh(self) await db_session.refresh(self)
return self return self
except SQLAlchemyError as ex: except SQLAlchemyError as ex:
await logger.aerror(f"Error inserting instance of {self}: {repr(ex)}") await logger.aerror(f"Error inserting instance of {self}: {repr(ex)}")
raise HTTPException( raise # This will make the exception handler catch it
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex
async def delete(self, db_session: AsyncSession): async def delete(self, db_session: AsyncSession):
"""
:param db_session:
:return:
"""
try: try:
await db_session.delete(self) await db_session.delete(self)
await db_session.commit()
return True return True
except SQLAlchemyError as ex: except SQLAlchemyError as ex:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex) status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex ) from ex
async def update(self, db: AsyncSession, **kwargs): async def update(self, **kwargs):
"""
:param db:
:param kwargs
:return:
"""
try: try:
for k, v in kwargs.items(): for k, v in kwargs.items():
setattr(self, k, v) setattr(self, k, v)
return await db.commit() return True
except SQLAlchemyError as ex: except SQLAlchemyError as ex:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex) status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex ) from ex
async def save_or_update(self, db: AsyncSession): async def save_or_update(self, db_session: AsyncSession):
try: try:
db.add(self) db_session.add(self)
return await db.commit() await db_session.flush()
return True
except IntegrityError as exception: except IntegrityError as exception:
if isinstance(exception.orig, UniqueViolationError): if isinstance(exception.orig, UniqueViolationError):
return await db.merge(self) return await db_session.merge(self)
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=repr(exception), detail=repr(exception),
) from exception ) from exception
finally: finally:
await db.close() await db_session.close()

View File

@ -7,7 +7,9 @@ config = ConfigDict(from_attributes=True)
class RandomStuff(BaseModel): class RandomStuff(BaseModel):
chaos: dict[str, Any] = Field(..., description="JSON data for chaos field") chaos: dict[str, Any] = Field(
..., description="Pretty chaotic JSON data can be added here..."
)
class StuffSchema(BaseModel): class StuffSchema(BaseModel):

View File