From 7509ff0e1582feff089f940bf7a7bb8f0c3d06fa Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 18 Oct 2021 14:18:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=BA=E8=84=B8=E8=AF=86=E5=88=AB=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_client/.env.production | 3 +- .../hrm/migrations/0003_employee_face_data.py | 18 ++++ hb_server/apps/hrm/models.py | 5 +- hb_server/apps/hrm/serializers.py | 5 +- hb_server/apps/hrm/urls.py | 3 +- hb_server/apps/hrm/views.py | 96 ++++++++++++++++++- hb_server/apps/system/serializers.py | 2 - hb_server/apps/system/urls.py | 5 +- hb_server/apps/system/views.py | 43 +-------- 9 files changed, 128 insertions(+), 52 deletions(-) create mode 100644 hb_server/apps/hrm/migrations/0003_employee_face_data.py diff --git a/hb_client/.env.production b/hb_client/.env.production index 484e806..b79ed31 100644 --- a/hb_client/.env.production +++ b/hb_client/.env.production @@ -2,5 +2,6 @@ ENV = 'production' # base api -VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' +#VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' +VUE_APP_BASE_API = 'http://127.0.0.1:8000/api' diff --git a/hb_server/apps/hrm/migrations/0003_employee_face_data.py b/hb_server/apps/hrm/migrations/0003_employee_face_data.py new file mode 100644 index 0000000..1823ad2 --- /dev/null +++ b/hb_server/apps/hrm/migrations/0003_employee_face_data.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-10-18 05:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('hrm', '0002_auto_20210924_1127'), + ] + + operations = [ + migrations.AddField( + model_name='employee', + name='face_data', + field=models.JSONField(blank=True, null=True, verbose_name='人脸识别数据'), + ), + ] diff --git a/hb_server/apps/hrm/models.py b/hb_server/apps/hrm/models.py index c448e64..1176416 100644 --- a/hb_server/apps/hrm/models.py +++ b/hb_server/apps/hrm/models.py @@ -28,9 +28,12 @@ class Employee(CommonAModel): academic = models.CharField('学历', max_length=50, null=True, blank=True) jobstate = models.IntegerField('在职状态', choices=jobstate_choices, default=1) job = models.ForeignKey(Position, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='岗位') + face_data = models.JSONField('人脸识别数据', null=True, blank=True) class Meta: verbose_name = '员工补充信息' verbose_name_plural = verbose_name def __str__(self): - return self.name \ No newline at end of file + return self.name + + diff --git a/hb_server/apps/hrm/serializers.py b/hb_server/apps/hrm/serializers.py index 96ab4df..7a14400 100644 --- a/hb_server/apps/hrm/serializers.py +++ b/hb_server/apps/hrm/serializers.py @@ -1,6 +1,6 @@ from apps.system.models import User from rest_framework.serializers import ModelSerializer - +from rest_framework import serializers from .models import Employee from apps.system.serializers import UserListSerializer, UserSimpleSerializer from django.db.models.query import Prefetch @@ -20,3 +20,6 @@ class EmployeeSerializer(ModelSerializer): # queryset=User.objects.filter(employee_user__isnull=True)) # ) # return queryset + +class FaceLoginSerializer(serializers.Serializer): + base64 = serializers.CharField() diff --git a/hb_server/apps/hrm/urls.py b/hb_server/apps/hrm/urls.py index bd532d0..293124c 100644 --- a/hb_server/apps/hrm/urls.py +++ b/hb_server/apps/hrm/urls.py @@ -1,12 +1,13 @@ from django.db.models import base from rest_framework import urlpatterns -from apps.hrm.views import EmployeeViewSet +from apps.hrm.views import EmployeeViewSet, FaceLogin from django.urls import path, include from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register('employee', EmployeeViewSet, basename='employee') urlpatterns = [ + path('facelogin/', FaceLogin.as_view()), path('', include(router.urls)), ] diff --git a/hb_server/apps/hrm/views.py b/hb_server/apps/hrm/views.py index 843fa96..ffb8df3 100644 --- a/hb_server/apps/hrm/views.py +++ b/hb_server/apps/hrm/views.py @@ -1,9 +1,34 @@ from django.shortcuts import render +from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from apps.hrm.models import Employee -from apps.hrm.serializers import EmployeeSerializer +from apps.hrm.serializers import EmployeeSerializer, FaceLoginSerializer +import face_recognition +from django.conf import settings +from django.core.cache import cache +import logging +from rest_framework.generics import CreateAPIView +from rest_framework import status +from rest_framework_simplejwt.tokens import RefreshToken + +from apps.system.models import User +logger = logging.getLogger('log') + + +def load_face_data(username:int, path:str): + """ + 将某用户face_encoding加载进缓存 + """ + face_datas = cache.get_or_set('face_datas', {}, timeout=None) + photo_path = settings.BASE_DIR + path + picture_of_me = face_recognition.load_image_file(photo_path) + my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] + face_datas[username] = my_face_encoding + cache.set('face_datas', face_datas, timeout=None) + return my_face_encoding + # Create your views here. class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMixin, RetrieveModelMixin, GenericViewSet): """ @@ -12,4 +37,71 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix perms_map = {'get': '*', 'put': 'employee_update'} queryset = Employee.objects.all() serializer_class = EmployeeSerializer - ordering = ['-pk'] \ No newline at end of file + ordering = ['-pk'] + + def perform_update(self, serializer): + instance = serializer.save(update_by = self.request.user) + try: + photo_path = settings.BASE_DIR + instance.photo + picture_of_me = face_recognition.load_image_file(photo_path) + my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] + instance.face_data = my_face_encoding.tolist() + instance.save() + except: + logger.error('人脸识别出错') + +import uuid +import base64 +import os + +def tran64(s): + missing_padding = len(s) % 4 + if missing_padding != 0: + s = s+'='* (4 - missing_padding) + return s + +class FaceLogin(CreateAPIView): + authentication_classes = [] + permission_classes = [] + serializer_class = FaceLoginSerializer + + + def create(self, request, *args, **kwargs): + """ + 人脸识别登录 + """ + # serializer = FaceLoginSerializer(data=request.data) + # serializer.is_valid(raise_exception=True) + filename = str(uuid.uuid4()) + filepath = settings.BASE_DIR +'/temp/' + filename +'.png' + with open(filepath, 'wb') as f: + data = tran64(request.data.get('base64').replace(' ', '+')) + f.write(base64.urlsafe_b64decode(data)) + # picture_of_me = face_recognition.load_image_file(settings.BASE_DIR +'/temp/me.png') + # my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] + #results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding, tolerance=0.2) + try: + unknown_picture = face_recognition.load_image_file(filepath) + unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0] + os.remove(filepath) + except: + logger.error('解码失败') + + # 匹配人脸库 + user_faces = Employee.objects.filter(face_data__isnull=False, user__is_active=True).values('user', 'face_data') + user_l = [] + face_l = [] + for i in user_faces: + user_l.append(i['user']) + face_l.append(i['face_data']) + + results = face_recognition.compare_faces(face_l, unknown_face_encoding, tolerance=0.2) + for index, value in enumerate(results): + if value: + # 识别成功 + refresh = RefreshToken.for_user(User.objects.get(id=user_l[index])) + return Response({ + 'refresh': str(refresh), + 'access': str(refresh.access_token), + }) + return Response('未找到对应用户', status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/hb_server/apps/system/serializers.py b/hb_server/apps/system/serializers.py index a39e88b..10636ea 100644 --- a/hb_server/apps/system/serializers.py +++ b/hb_server/apps/system/serializers.py @@ -199,5 +199,3 @@ class UserCreateSerializer(serializers.ModelSerializer): return phone -class FaceLoginSerializer(serializers.Serializer): - base64 = serializers.CharField() \ No newline at end of file diff --git a/hb_server/apps/system/urls.py b/hb_server/apps/system/urls.py index 55e1420..02a4ecb 100644 --- a/hb_server/apps/system/urls.py +++ b/hb_server/apps/system/urls.py @@ -1,5 +1,5 @@ from django.urls import path, include -from .views import FaceLogin, TaskList, UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView, DictTypeViewSet, DictViewSet, PTaskViewSet +from .views import TaskList, UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView, DictTypeViewSet, DictViewSet, PTaskViewSet from rest_framework import routers @@ -15,6 +15,5 @@ router.register('ptask', PTaskViewSet, basename="ptask") urlpatterns = [ path('', include(router.urls)), path('task/', TaskList.as_view()), - path('test/', TestView.as_view()), - path('facelogin/', FaceLogin.as_view()) + path('test/', TestView.as_view()) ] diff --git a/hb_server/apps/system/views.py b/hb_server/apps/system/views.py index 2ee96a6..65a1320 100644 --- a/hb_server/apps/system/views.py +++ b/hb_server/apps/system/views.py @@ -21,6 +21,7 @@ from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet, ModelViewSet from rest_framework_simplejwt.tokens import RefreshToken from rest_framework.exceptions import ValidationError, ParseError +from apps.hrm.models import Employee from utils.queryset import get_child_queryset2 from .filters import UserFilter @@ -29,7 +30,7 @@ from .models import (Dict, DictType, File, Organization, Permission, Position, Role, User) from .permission import RbacPermission, get_permission_list from .permission_data import RbacFilterSet -from .serializers import (DictSerializer, DictTypeSerializer, FaceLoginSerializer, FileSerializer, +from .serializers import (DictSerializer, DictTypeSerializer, FileSerializer, OrganizationSerializer, PermissionSerializer, PositionSerializer, RoleSerializer, PTaskSerializer,PTaskCreateUpdateSerializer, UserCreateSerializer, UserListSerializer, @@ -352,43 +353,3 @@ class FileViewSet(CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, ListM instance.save() - -#import face_recognition -import uuid -import base64 -import os - -def tran64(s): - missing_padding = len(s) % 4 - if missing_padding != 0: - s = s+'='* (4 - missing_padding) - return s - -class FaceLogin(CreateAPIView): - authentication_classes = [] - permission_classes = [] - serializer_class = FaceLoginSerializer - - - def create(self, request, *args, **kwargs): - """ - 人脸识别登录 - """ - # serializer = FaceLoginSerializer(data=request.data) - # serializer.is_valid(raise_exception=True) - filename = str(uuid.uuid4()) - filepath = settings.BASE_DIR +'/temp/' + filename +'.png' - with open(filepath, 'wb') as f: - data = tran64(request.data.get('base64').replace(' ', '+')) - f.write(base64.urlsafe_b64decode(data)) - # picture_of_me = face_recognition.load_image_file(settings.BASE_DIR +'/temp/me.png') - # my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] - # unknown_picture = face_recognition.load_image_file(filepath) - # unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0] - #results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding, tolerance=0.2) - os.remove(filepath) - # if results[0] == True: - # return Response('这是曹前明') - # else: - # return Response('这不是曹前明') -