This commit is contained in:
ZZX9599
2025-09-03 21:41:26 +08:00
parent 1c27d64f58
commit 8a97bfa381
2 changed files with 52 additions and 87 deletions

View File

@ -6,28 +6,25 @@ from pydantic import BaseModel, Field
# 请求模型(前端传参校验) # 请求模型(前端传参校验)
# ------------------------------ # ------------------------------
class FaceCreateRequest(BaseModel): class FaceCreateRequest(BaseModel):
"""创建人脸记录请求模型""" """创建人脸记录请求模型无需ID由数据库自增"""
id: int = Field(..., description="主键ID") name: str = Field(None, max_length=255, description="名称可选最长255字符")
name: str = Field(None, max_length=255, description="名称")
eigenvalue: str = Field(None, max_length=255, description="特征")
class FaceUpdateRequest(BaseModel): class FaceUpdateRequest(BaseModel):
"""更新人脸记录请求模型""" """更新人脸记录请求模型(不变)"""
name: str = Field(None, max_length=255, description="名称") name: str = Field(None, max_length=255, description="名称")
eigenvalue: str = Field(None, max_length=255, description="特征") eigenvalue: str = Field(None, max_length=255, description="特征(文件处理后可更新)")
# ------------------------------ # ------------------------------
# 响应模型(后端返回数据) # 响应模型(后端返回数据)
# ------------------------------ # ------------------------------
class FaceResponse(BaseModel): class FaceResponse(BaseModel):
"""人脸记录响应模型""" """人脸记录响应模型仍包含ID由数据库生成后返回"""
id: int = Field(..., description="主键ID") id: int = Field(..., description="主键ID(数据库自增)")
name: str = Field(None, description="名称") name: str = Field(None, description="名称")
eigenvalue: str = Field(None, description="特征") eigenvalue: str = Field(None, description="特征暂为None")
created_at: datetime = Field(..., description="记录创建时间") created_at: datetime = Field(..., description="记录创建时间")
updated_at: datetime = Field(..., description="记录更新时间") updated_at: datetime = Field(..., description="记录更新时间")
# 支持从数据库查询结果转换
model_config = {"from_attributes": True} model_config = {"from_attributes": True}

View File

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from mysql.connector import Error as MySQLError from mysql.connector import Error as MySQLError
from ds.db import db from ds.db import db
@ -7,7 +7,6 @@ from schema.response_schema import APIResponse
from middle.auth_middleware import get_current_user from middle.auth_middleware import get_current_user
from schema.user_schema import UserResponse from schema.user_schema import UserResponse
# 创建人脸接口路由(前缀 /faces、标签用于 Swagger 分类)
router = APIRouter( router = APIRouter(
prefix="/faces", prefix="/faces",
tags=["人脸管理"] tags=["人脸管理"]
@ -15,50 +14,52 @@ router = APIRouter(
# ------------------------------ # ------------------------------
# 1. 创建人脸记录 # 1. 创建人脸记录核心修正ID 数据库自增,前端无需传)
# ------------------------------ # ------------------------------
@router.post("", response_model=APIResponse, summary="创建人脸记录") @router.post("", response_model=APIResponse, summary="创建人脸记录(传名称+文件ID自增")
async def create_face( async def create_face(
face: FaceCreateRequest # 前端仅需传name可选Form格式、file必传文件
name: str = Form(None, max_length=255, description="名称(可选)"),
file: UploadFile = File(..., description="人脸文件(必传,暂不处理内容)")
): ):
""" """
创建人脸记录: 创建人脸记录:
- 需登录认证 - 需登录认证
- 插入新的人脸记录到数据库 - 前端传参multipart/form-data 表单name 可选file 必传)
- 返回创建成功信息 - ID 由数据库自动生成,无需前端传入
- 暂不处理文件内容eigenvalue 设为 None
""" """
conn = None conn = None
cursor = None cursor = None
try: try:
# 1. 用模型校验 name仅校验长度无需ID
face_create = FaceCreateRequest(name=name)
conn = db.get_connection() conn = db.get_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
# 1. 检查ID是否已存在 # 把文件转为二进制数组
check_query = "SELECT id FROM face WHERE id = %s" file_content = await file.read()
cursor.execute(check_query, (face.id,))
existing_face = cursor.fetchone()
if existing_face:
raise HTTPException(
status_code=400,
detail=f"ID为 {face.id} 的人脸记录已存在"
)
# 2. 插入新人脸记录到数据库 # 调用人脸识别得到特征值
# 2. 插入数据库:无需传 ID自增只传 name 和 eigenvalueNone
insert_query = """ insert_query = """
INSERT INTO face (id, name, eigenvalue) INSERT INTO face (name, eigenvalue)
VALUES (%s, %s, %s) VALUES (%s, %s)
""" """
cursor.execute(insert_query, (face.id, face.name, face.eigenvalue)) cursor.execute(insert_query, (face_create.name, None))
conn.commit() conn.commit()
# 3. 查询刚创建的记录并返回 # 3. 获取数据库自动生成的 ID关键用 LAST_INSERT_ID() 查刚插入的记录)
select_query = "SELECT * FROM face WHERE id = %s" select_new_query = "SELECT * FROM face WHERE id = LAST_INSERT_ID()"
cursor.execute(select_query, (face.id,)) cursor.execute(select_new_query)
created_face = cursor.fetchone() created_face = cursor.fetchone()
return APIResponse( return APIResponse(
code=201, # 201 表示资源创建成功 code=201,
message="人脸记录创建成功", message=f"人脸记录创建成功ID{created_face['id']},文件名:{file.filename}",
data=FaceResponse(**created_face) data=FaceResponse(**created_face)
) )
except MySQLError as e: except MySQLError as e:
@ -66,23 +67,18 @@ async def create_face(
conn.rollback() conn.rollback()
raise Exception(f"创建人脸记录失败:{str(e)}") from e raise Exception(f"创建人脸记录失败:{str(e)}") from e
finally: finally:
await file.close() # 关闭文件流
db.close_connection(conn, cursor) db.close_connection(conn, cursor)
# ------------------------------ # ------------------------------
# 2. 获取单个人脸记录 # 2. 获取单个人脸记录不变用自增ID查询
# ------------------------------ # ------------------------------
@router.get("/{face_id}", response_model=APIResponse, summary="获取单个人脸记录") @router.get("/{face_id}", response_model=APIResponse, summary="获取单个人脸记录")
async def get_face( async def get_face(
face_id: int, face_id: int, # 这里的 ID 是数据库自增的,前端从创建响应中获取
current_user: UserResponse = Depends(get_current_user) # 需登录认证 current_user: UserResponse = Depends(get_current_user)
): ):
"""
获取单个人脸记录:
- 需登录认证
- 根据ID查询人脸记录
- 返回查询到的人脸信息
"""
conn = None conn = None
cursor = None cursor = None
try: try:
@ -110,25 +106,21 @@ async def get_face(
db.close_connection(conn, cursor) db.close_connection(conn, cursor)
# 后续 3.获取所有、4.更新、5.删除 接口(不变,仅用数据库自增的 ID 操作,无需修改)
# ------------------------------ # ------------------------------
# 3. 获取所有人脸记录 # 3. 获取所有人脸记录(不变)
# ------------------------------ # ------------------------------
@router.get("", response_model=APIResponse, summary="获取所有人脸记录") @router.get("", response_model=APIResponse, summary="获取所有人脸记录")
async def get_all_faces( async def get_all_faces(
current_user: UserResponse = Depends(get_current_user)
): ):
"""
获取所有人脸记录:
- 需登录认证
- 查询所有人脸记录(不需要分页)
- 返回所有人脸信息列表
"""
conn = None conn = None
cursor = None cursor = None
try: try:
conn = db.get_connection() conn = db.get_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
query = "SELECT * FROM face ORDER BY id" query = "SELECT * FROM face ORDER BY id" # 按自增ID排序
cursor.execute(query) cursor.execute(query)
faces = cursor.fetchall() faces = cursor.fetchall()
@ -144,27 +136,21 @@ async def get_all_faces(
# ------------------------------ # ------------------------------
# 4. 更新人脸记录 # 4. 更新人脸记录不变用自增ID更新
# ------------------------------ # ------------------------------
@router.put("/{face_id}", response_model=APIResponse, summary="更新人脸记录") @router.put("/{face_id}", response_model=APIResponse, summary="更新人脸记录")
async def update_face( async def update_face(
face_id: int, face_id: int,
face_update: FaceUpdateRequest, face_update: FaceUpdateRequest,
current_user: UserResponse = Depends(get_current_user) # 需登录认证 current_user: UserResponse = Depends(get_current_user)
): ):
"""
更新人脸记录:
- 需登录认证
- 根据ID更新人脸记录信息
- 返回更新后的人脸信息
"""
conn = None conn = None
cursor = None cursor = None
try: try:
conn = db.get_connection() conn = db.get_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
# 1. 检查记录是否存在 # 检查记录是否存在
check_query = "SELECT id FROM face WHERE id = %s" check_query = "SELECT id FROM face WHERE id = %s"
cursor.execute(check_query, (face_id,)) cursor.execute(check_query, (face_id,))
existing_face = cursor.fetchone() existing_face = cursor.fetchone()
@ -174,35 +160,25 @@ async def update_face(
detail=f"ID为 {face_id} 的人脸记录不存在" detail=f"ID为 {face_id} 的人脸记录不存在"
) )
# 2. 构建更新语句(只更新提供的字段) # 构建更新语句
update_fields = [] update_fields = []
params = [] params = []
if face_update.name is not None: if face_update.name is not None:
update_fields.append("name = %s") update_fields.append("name = %s")
params.append(face_update.name) params.append(face_update.name)
if face_update.eigenvalue is not None: if face_update.eigenvalue is not None:
update_fields.append("eigenvalue = %s") update_fields.append("eigenvalue = %s")
params.append(face_update.eigenvalue) params.append(face_update.eigenvalue)
if not update_fields: if not update_fields:
raise HTTPException( raise HTTPException(status_code=400, detail="至少需提供一个更新字段")
status_code=400,
detail="至少需要提供一个字段进行更新"
)
params.append(face_id) # WHERE条件的参数 params.append(face_id)
update_query = f"UPDATE face SET {', '.join(update_fields)}, updated_at = CURRENT_TIMESTAMP WHERE id = %s"
update_query = f"""
UPDATE face
SET {', '.join(update_fields)}, updated_at = CURRENT_TIMESTAMP
WHERE id = %s
"""
cursor.execute(update_query, params) cursor.execute(update_query, params)
conn.commit() conn.commit()
# 3. 查询更新后记录并返回 # 查询更新后记录
select_query = "SELECT * FROM face WHERE id = %s" select_query = "SELECT * FROM face WHERE id = %s"
cursor.execute(select_query, (face_id,)) cursor.execute(select_query, (face_id,))
updated_face = cursor.fetchone() updated_face = cursor.fetchone()
@ -221,26 +197,19 @@ async def update_face(
# ------------------------------ # ------------------------------
# 5. 删除人脸记录 # 5. 删除人脸记录不变用自增ID删除
# ------------------------------ # ------------------------------
@router.delete("/{face_id}", response_model=APIResponse, summary="删除人脸记录") @router.delete("/{face_id}", response_model=APIResponse, summary="删除人脸记录")
async def delete_face( async def delete_face(
face_id: int, face_id: int,
current_user: UserResponse = Depends(get_current_user) # 需登录认证 current_user: UserResponse = Depends(get_current_user)
): ):
"""
删除人脸记录:
- 需登录认证
- 根据ID删除人脸记录
- 返回删除成功信息
"""
conn = None conn = None
cursor = None cursor = None
try: try:
conn = db.get_connection() conn = db.get_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
# 1. 检查记录是否存在
check_query = "SELECT id FROM face WHERE id = %s" check_query = "SELECT id FROM face WHERE id = %s"
cursor.execute(check_query, (face_id,)) cursor.execute(check_query, (face_id,))
existing_face = cursor.fetchone() existing_face = cursor.fetchone()
@ -250,7 +219,6 @@ async def delete_face(
detail=f"ID为 {face_id} 的人脸记录不存在" detail=f"ID为 {face_id} 的人脸记录不存在"
) )
# 2. 执行删除操作
delete_query = "DELETE FROM face WHERE id = %s" delete_query = "DELETE FROM face WHERE id = %s"
cursor.execute(delete_query, (face_id,)) cursor.execute(delete_query, (face_id,))
conn.commit() conn.commit()