from django.shortcuts import render from django.utils import timezone from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin from apps.hrm.filters import ClockRecordFilterSet from apps.hrm.services import HRMService from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from apps.hrm.models import ClockRecord, Employee from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, 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 rest_framework import exceptions from apps.system.models import User from apps.system.serializers import UserSimpleSerializer from rest_framework.permissions import AllowAny 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): """ 员工详细信息 """ perms_map = {'get': '*', 'put': 'employee_update'} queryset = Employee.objects.all() serializer_class = EmployeeSerializer 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('人脸识别出错') class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet): """ 打卡记录 """ perms_map = {'get':'*', 'post':'*'} authentication_classes = [] permission_classes = [AllowAny] queryset = ClockRecord.objects.select_related('create_by').all() serializer_class = ClockRecordListSerializer filterset_class = ClockRecordFilterSet ordering = ['-pk'] def get_serializer_class(self): if self.action == 'create': return FaceClockCreateSerializer return super().get_serializer_class() def create(self, request, *args, **kwargs): now = timezone.localtime() if 8<=now.hour<=17: base64_data = base64.urlsafe_b64decode(tran64( request.data.get('base64').replace(' ', '+'))) user, msg = HRMService.face_compare_from_base64(base64_data) if user: ins, created = ClockRecord.objects.get_or_create( create_by=request.user, create_time__hour__range = [8,18], create_time__year=now.year, create_time__month=now.month, create_time__day=now.day, defaults={ 'type':ClockRecord.ClOCK_WORK1, 'create_by':user, 'create_time':now }) if not created: ins.create_time = now ins.save() # 设为在岗 user.is_atwork = True user.save() return Response(UserSimpleSerializer(instance=user).data) return Response(msg, status=status.HTTP_400_BAD_REQUEST) return Response('非打卡时间范围', status=status.HTTP_400_BAD_REQUEST) import base64 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): """ 人脸识别登录 """ base64_data = base64.urlsafe_b64decode(tran64(request.data.get('base64').replace(' ', '+'))) user, msg = HRMService.face_compare_from_base64(base64_data) if user: refresh = RefreshToken.for_user(user) return Response({ 'refresh': str(refresh), 'access': str(refresh.access_token), 'username':user.username }) return Response(msg, status=status.HTTP_400_BAD_REQUEST)