mirror of
https://github.com/grillazz/fastapi-sqlalchemy-asyncpg.git
synced 2025-08-26 16:40:40 +03:00
wip: crud refactor
This commit is contained in:
parent
93f2e66bd0
commit
d722504e55
@ -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
|
||||||
|
@ -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
|
||||||
|
16
app/main.py
16
app/main.py
@ -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})
|
||||||
|
@ -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()
|
||||||
|
@ -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):
|
||||||
|
0
tests/api/test_chaotic_stuff.py
Normal file
0
tests/api/test_chaotic_stuff.py
Normal file
Loading…
x
Reference in New Issue
Block a user