Files
YG-Datasets/backend/app/api/v1/projects/__init__.py
Developer cc2e73c595 feat(backend): 更新 API 支持语义分割和 embedding 配置
- chunks API 添加 embedding 配置字段
- projects API 更新路由和方法

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 16:08:08 +08:00

121 lines
3.8 KiB
Python

"""
Projects API Router
"""
import logging
import shutil
from pathlib import Path
from typing import List, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.response import ApiResponse, PaginatedResponse
from app.core.database import get_db
from app.core.exceptions import NotFoundException
from app.core.crud import CRUDBase
from app.models.models import Project
from app.schemas.project import (
ProjectCreate,
ProjectUpdate,
ProjectResponse,
ProjectCreateSchema,
ProjectUpdateSchema
)
router = APIRouter()
logger = logging.getLogger("yg_dataset.projects")
# Initialize CRUD
project_crud = CRUDBase(Project)
@router.get("", response_model=PaginatedResponse)
async def list_projects(
page: int = Query(1, ge=1, description="Page number"),
page_size: int = Query(20, ge=1, le=100, description="Page size"),
db: AsyncSession = Depends(get_db)
):
"""List all projects with pagination"""
logger.info(f"Listing projects - page: {page}, page_size: {page_size}")
skip = (page - 1) * page_size
projects, total = await project_crud.get_multi(
db,
skip=skip,
limit=page_size,
order_by="created_at",
descending=True
)
logger.info(f"Found {total} projects, returning {len(projects)} items")
project_responses = [ProjectResponse.model_validate(p) for p in projects]
return PaginatedResponse.ok(
items=project_responses,
page=page,
page_size=page_size,
total=total
)
@router.post("", response_model=ApiResponse)
async def create_project(
project: ProjectCreateSchema,
db: AsyncSession = Depends(get_db)
):
"""Create a new project"""
logger.info(f"Creating project: name={project.name}, description={project.description}")
db_project = await project_crud.create(db, project)
logger.info(f"Project created successfully: id={db_project.id}")
return ApiResponse.ok(
data={"id": str(db_project.id)},
message="Project created successfully"
)
@router.get("/{project_id}", response_model=ApiResponse)
async def get_project(
project_id: UUID,
db: AsyncSession = Depends(get_db)
):
"""Get project by ID"""
logger.info(f"Getting project: id={project_id}")
project = await project_crud.get_or_raise(db, project_id, "Project")
logger.info(f"Found project: name={project.name}")
return ApiResponse.ok(data=ProjectResponse.model_validate(project))
@router.put("/{project_id}", response_model=ApiResponse)
async def update_project(
project_id: UUID,
project: ProjectUpdateSchema,
db: AsyncSession = Depends(get_db)
):
"""Update project"""
logger.info(f"Updating project: id={project_id}")
db_project = await project_crud.get_or_raise(db, project_id, "Project")
updated_project = await project_crud.update(db, db_project, project)
logger.info(f"Project updated: name={updated_project.name}")
return ApiResponse.ok(
data=ProjectResponse.model_validate(updated_project),
message="Project updated successfully"
)
@router.delete("/{project_id}", response_model=ApiResponse)
async def delete_project(
project_id: UUID,
db: AsyncSession = Depends(get_db)
):
"""Delete project"""
logger.info(f"Deleting project: id={project_id}")
await project_crud.get_or_raise(db, project_id, "Project")
await project_crud.delete(db, project_id)
# 删除项目对应的本地数据目录
project_data_dir = Path("/data/code/YG-Datasets/data") / str(project_id)
if project_data_dir.exists():
shutil.rmtree(project_data_dir)
logger.info(f"Project data directory deleted: {project_data_dir}")
logger.info(f"Project deleted: id={project_id}")
return ApiResponse.ok(message="Project deleted successfully")