人脸
This commit is contained in:
@ -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}
|
|
@ -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 和 eigenvalue(None)
|
||||||
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()
|
||||||
|
Reference in New Issue
Block a user