Spaces:
Runtime error
Runtime error
File size: 4,915 Bytes
75557db | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | """
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)
|