Initial lightweight AI agent admin
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from typing import Any, Type
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
from app.core.database import get_db
|
||||
from app.models import User
|
||||
from app.schemas.common import Page, ResponseModel
|
||||
|
||||
|
||||
def crud_router(
|
||||
*,
|
||||
prefix: str,
|
||||
tags: list[str],
|
||||
model: Type,
|
||||
create_schema: Type[BaseModel],
|
||||
update_schema: Type[BaseModel],
|
||||
out_schema: Type[BaseModel],
|
||||
) -> APIRouter:
|
||||
router = APIRouter(prefix=prefix, tags=tags, dependencies=[Depends(get_current_user)])
|
||||
|
||||
@router.get("", response_model=Page[out_schema]) # type: ignore[valid-type]
|
||||
async def list_items(
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
keyword: str | None = Query(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
conditions = [model.is_deleted == False]
|
||||
if keyword and hasattr(model, "name"):
|
||||
conditions.append(model.name.ilike(f"%{keyword}%"))
|
||||
query = select(model).where(*conditions)
|
||||
total = await db.scalar(select(func.count()).select_from(query.subquery()))
|
||||
result = await db.execute(
|
||||
query.order_by(model.sort.desc(), model.created_at.desc()).offset((page - 1) * page_size).limit(page_size)
|
||||
)
|
||||
return Page(items=result.scalars().all(), total=total or 0, page=page, page_size=page_size)
|
||||
|
||||
@router.get("/{item_id}", response_model=out_schema) # type: ignore[valid-type]
|
||||
async def get_item(item_id: str, db: AsyncSession = Depends(get_db)):
|
||||
item = await db.get(model, item_id)
|
||||
if not item or item.is_deleted:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return item
|
||||
|
||||
@router.post("", response_model=out_schema) # type: ignore[valid-type]
|
||||
async def create_item(payload: create_schema, db: AsyncSession = Depends(get_db)): # type: ignore[valid-type]
|
||||
item = model(**payload.model_dump())
|
||||
db.add(item)
|
||||
await db.commit()
|
||||
await db.refresh(item)
|
||||
return item
|
||||
|
||||
@router.put("/{item_id}", response_model=out_schema) # type: ignore[valid-type]
|
||||
async def update_item(item_id: str, payload: update_schema, db: AsyncSession = Depends(get_db)): # type: ignore[valid-type]
|
||||
item = await db.get(model, item_id)
|
||||
if not item or item.is_deleted:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
data: dict[str, Any] = payload.model_dump(exclude_unset=True)
|
||||
for key, value in data.items():
|
||||
if hasattr(item, key):
|
||||
setattr(item, key, value)
|
||||
await db.commit()
|
||||
await db.refresh(item)
|
||||
return item
|
||||
|
||||
@router.delete("/{item_id}", response_model=ResponseModel)
|
||||
async def delete_item(item_id: str, db: AsyncSession = Depends(get_db)):
|
||||
item = await db.get(model, item_id)
|
||||
if not item or item.is_deleted:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
item.is_deleted = True
|
||||
await db.commit()
|
||||
return ResponseModel(message="deleted")
|
||||
|
||||
return router
|
||||
Reference in New Issue
Block a user