You've already forked DataMate
feat(annotation): 添加标注项目信息更新功能
- 引入 DatasetMappingUpdateRequest 请求模型支持 name、description、template_id 和 label_config 字段更新
- 在项目接口中添加 PUT /{project_id} 端点用于更新标注项目信息
- 实现更新逻辑包括映射记录查询、配置信息处理和数据库更新操作
- 集成标准响应格式返回更新结果
- 添加异常处理和日志记录确保操作可追溯性
This commit is contained in:
@@ -3,7 +3,7 @@ import math
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Path
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.db.session import get_db
|
||||
@@ -17,6 +17,7 @@ from ..service.template import AnnotationTemplateService
|
||||
from ..schema import (
|
||||
DatasetMappingCreateRequest,
|
||||
DatasetMappingCreateResponse,
|
||||
DatasetMappingUpdateRequest,
|
||||
DeleteDatasetResponse,
|
||||
DatasetMappingResponse,
|
||||
)
|
||||
@@ -382,3 +383,97 @@ async def delete_mapping(
|
||||
except Exception as e:
|
||||
logger.error(f"Error deleting mapping: {e}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
|
||||
@router.put("/{project_id}", response_model=StandardResponse[DatasetMappingResponse])
|
||||
async def update_mapping(
|
||||
project_id: str = Path(..., description="映射UUID(path param)"),
|
||||
request: DatasetMappingUpdateRequest = None,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
更新标注项目信息
|
||||
|
||||
通过 path 参数 `project_id` 指定要更新的映射(映射的 UUID)。
|
||||
支持更新的字段:
|
||||
- name: 标注项目名称
|
||||
- description: 标注项目描述
|
||||
- template_id: 标注模板ID
|
||||
- label_config: Label Studio XML配置
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Update mapping request received: project_id={project_id!r}")
|
||||
|
||||
service = DatasetMappingService(db)
|
||||
|
||||
# 使用 mapping UUID 查询映射记录
|
||||
mapping = await service.get_mapping_by_uuid(project_id)
|
||||
|
||||
if not mapping:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f"Mapping not found: {project_id}"
|
||||
)
|
||||
|
||||
# 构建更新数据
|
||||
update_values = {}
|
||||
if request.name is not None:
|
||||
update_values["name"] = request.name
|
||||
|
||||
# 从 configuration 字段中读取和更新 description 和 label_config
|
||||
configuration = {}
|
||||
if mapping.configuration:
|
||||
configuration = mapping.configuration.copy() if isinstance(mapping.configuration, dict) else {}
|
||||
|
||||
if request.description is not None:
|
||||
configuration["description"] = request.description
|
||||
if request.label_config is not None:
|
||||
configuration["label_config"] = request.label_config
|
||||
|
||||
if configuration:
|
||||
update_values["configuration"] = configuration
|
||||
|
||||
if request.template_id is not None:
|
||||
update_values["template_id"] = request.template_id
|
||||
|
||||
if not update_values:
|
||||
# 没有要更新的字段,直接返回当前数据
|
||||
return StandardResponse(
|
||||
code=200,
|
||||
message="success",
|
||||
data=mapping
|
||||
)
|
||||
|
||||
# 执行更新
|
||||
from datetime import datetime
|
||||
update_values["updated_at"] = datetime.now()
|
||||
|
||||
result = await db.execute(
|
||||
update(LabelingProject)
|
||||
.where(LabelingProject.id == project_id)
|
||||
.values(**update_values)
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
if result.rowcount == 0:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to update mapping"
|
||||
)
|
||||
|
||||
# 重新获取更新后的数据
|
||||
updated_mapping = await service.get_mapping_by_uuid(project_id)
|
||||
|
||||
logger.info(f"Successfully updated mapping: {project_id}")
|
||||
|
||||
return StandardResponse(
|
||||
code=200,
|
||||
message="success",
|
||||
data=updated_mapping
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating mapping: {e}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
@@ -39,9 +39,22 @@ class DatasetMappingCreateResponse(BaseResponseModel):
|
||||
labeling_project_id: str = Field(..., description="Label Studio项目ID")
|
||||
labeling_project_name: str = Field(..., description="Label Studio项目名称")
|
||||
|
||||
class DatasetMappingUpdateRequest(BaseResponseModel):
|
||||
"""数据集映射 更新 请求模型"""
|
||||
dataset_id: Optional[str] = Field(None, description="源数据集ID")
|
||||
class DatasetMappingUpdateRequest(BaseModel):
|
||||
"""数据集映射 更新 请求模型
|
||||
|
||||
支持更新的字段:
|
||||
- name: 标注项目名称
|
||||
- description: 标注项目描述
|
||||
- template_id: 标注模板ID
|
||||
- label_config: Label Studio XML配置
|
||||
"""
|
||||
name: Optional[str] = Field(None, alias="name", description="标注项目名称")
|
||||
description: Optional[str] = Field(None, alias="description", description="标注项目描述")
|
||||
template_id: Optional[str] = Field(None, alias="templateId", description="标注模板ID")
|
||||
label_config: Optional[str] = Field(None, alias="labelConfig", description="Label Studio XML配置")
|
||||
|
||||
class Config:
|
||||
validate_by_name = True
|
||||
|
||||
class DatasetMappingResponse(BaseModel):
|
||||
"""数据集映射 查询 响应模型"""
|
||||
|
||||
Reference in New Issue
Block a user