face-recognition-api / api /persons.py
chrisnguyenx's picture
Deploy FaceID AI Service via Docker
75557db
Raw
History Blame Contribute Delete
4.92 kB
"""
api/persons.py — Endpoints quản lý thông tin Person
GET /api/persons — Danh sách tất cả persons có embedding
PUT /api/persons/<id> — Cập nhật thông tin cá nhân
DELETE /api/persons/<id> — Xóa person (cascade: visits, embeddings, logs, MongoDB)
DELETE /api/db/<filename> — Legacy alias xóa theo tên file (backward compat)
"""
import logging
from flask import Blueprint, jsonify, request
from face_model.analyzer import face_analyzer
from storage.mongo_storage import mongo_storage
from storage.pg_storage import pg_storage
logger = logging.getLogger("api.persons")
bp = Blueprint("persons", __name__, url_prefix="/api")
@bp.get("/persons")
def list_persons():
"""
GET /api/persons
Trả về danh sách tất cả persons có face_embedding active.
"""
try:
persons = pg_storage.list_persons_with_faces()
for p in persons:
crop_id = p.get("face_crop_mongo_id", "")
p["face_url"] = f"/api/face-crops/{crop_id}" if crop_id else None
return jsonify({
"total": len(persons),
"persons": persons,
}), 200
except Exception as e:
logger.error(f"[list_persons] Error: {e}", exc_info=True)
return jsonify({"error": {
"code": "FETCH_FAILED",
"message": f"Không thể lấy danh sách persons: {e}",
"status": 500,
}}), 500
@bp.put("/persons/<person_id>")
def update_person(person_id: str):
"""
PUT /api/persons/<person_id>
Body JSON: { full_name, date_of_birth?, phone_number?, address? }
"""
body = request.get_json(silent=True)
if not body or "full_name" not in body:
return jsonify({"error": {
"code": "VALIDATION_ERROR",
"message": "Thiếu trường bắt buộc: full_name.",
"status": 400,
}}), 400
full_name = body["full_name"].strip()
date_of_birth = body.get("date_of_birth")
phone_number = body.get("phone_number")
address = body.get("address")
if not full_name:
return jsonify({"error": {
"code": "VALIDATION_ERROR",
"message": "full_name không được để trống.",
"status": 400,
}}), 400
try:
updated = pg_storage.update_person_info(
person_id=person_id,
full_name=full_name,
date_of_birth=date_of_birth,
phone_number=phone_number,
address=address,
)
if not updated:
return jsonify({"error": {
"code": "NOT_FOUND",
"message": f"Không tìm thấy person với ID: {person_id}",
"status": 404,
}}), 404
# Cập nhật tên trong RAM cache
face_analyzer.update_name_in_cache(person_id, full_name)
return jsonify({
"success": True,
"person_id": person_id,
"full_name": full_name,
"message": f"Đã cập nhật thông tin cho {full_name}.",
}), 200
except Exception as e:
logger.error(f"[update_person] Error: {e}", exc_info=True)
return jsonify({"error": {
"code": "UPDATE_FAILED",
"message": f"Không thể cập nhật thông tin: {e}",
"status": 500,
}}), 500
@bp.delete("/persons/<person_id>")
def delete_person(person_id: str):
"""
DELETE /api/persons/<person_id>
Xóa person và toàn bộ dữ liệu liên quan (cascade).
"""
try:
success, mongo_ids = pg_storage.delete_person(person_id)
if not success:
return jsonify({"error": {
"code": "NOT_FOUND",
"message": f"Không tìm thấy person với ID: {person_id}",
"status": 404,
}}), 404
# Xóa ảnh crop trên MongoDB
for mid in mongo_ids:
mongo_storage.delete_face_crop(mid)
# Xóa khỏi RAM cache
face_analyzer.remove_from_cache(person_id)
return jsonify({
"success": True,
"person_id": person_id,
"message": "Đã xóa person thành công.",
"total_faces": face_analyzer.total,
}), 200
except Exception as e:
logger.error(f"[delete_person] Error: {e}", exc_info=True)
return jsonify({"error": {
"code": "DELETE_FAILED",
"message": f"Không thể xóa person: {e}",
"status": 500,
}}), 500
# ── Legacy endpoints ───────────────────────────────────────────────────────
@bp.put("/person/<person_id>")
def update_person_legacy(person_id: str):
"""Legacy alias → PUT /api/persons/<person_id>"""
return update_person(person_id)