import base64 import hashlib from io import BytesIO from django import forms from django.core.exceptions import ValidationError from django.core.files.storage import default_storage from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from university.models import UserOnlineExam, UserOnlineExamFace, Upload from university.file_storage.utils import generate_random_file_path from university.tasks.online_exam import async_validate_examinee_id_face class ExamineeInfoForm(forms.Form): name = forms.CharField(required=True, max_length=64) chinese_id_number = forms.CharField(required=True, max_length=64) def __init__(self, user, user_online_exam, *args, **kwargs): self.user = user self.user_online_exam = user_online_exam super(ExamineeInfoForm, self).__init__(*args, **kwargs) def clean_chinese_id_number(self): chinese_id_number = self.cleaned_data.get('chinese_id_number') if chinese_id_number: # TODO if not (15 <= len(chinese_id_number) <= 18): raise ValidationError(_('invalid chinese ID number')) return chinese_id_number def save(self): self.user_online_exam.examinee_name = self.cleaned_data.get('name') self.user_online_exam.examinee_chinese_id = self.cleaned_data.get('chinese_id_number') self.user_online_exam.save(update_fields=['examinee_name', 'examinee_chinese_id']) identity_face = self.user_online_exam.identity_face identity_face.status = UserOnlineExamFace.STATUS_PENDING identity_face.save(update_fields=['status']) async_validate_examinee_id_face.delay(identity_face.id) class FaceIdentificationForm(forms.Form): image = forms.CharField(required=True) def __init__(self, user, user_online_exam, *args, **kwargs): self.user_online_exam = user_online_exam self.user = user super(FaceIdentificationForm, self).__init__(*args, **kwargs) def clean_image(self): image = self.cleaned_data.get('image') if image: if len(image) > (6 * 1 << 20): raise ValidationError('文件大小超过限制') if not image.startswith('data:image/'): raise ValidationError('图片格式错误, 格式应类似于: data:image/jpeg;base64,/9j/4AA....') return image def save(self): image = self.cleaned_data.get('image') content_type, base64string = image.split(':', 1)[1].split(';', 1) file_suffix = content_type.split('/')[1] base64string = base64string.split(',', 1)[1] img = base64.b64decode(base64string) content_hash = hashlib.sha1(img).hexdigest() file_obj = BytesIO() file_obj.write(img) file_obj.seek(0) file_path = '{}.{}'.format(generate_random_file_path(), file_suffix) default_storage.save(file_path, file_obj) upload = Upload.objects.create( user=self.user, original_filename=file_path, filesize=len(img), path=file_path, sha1=content_hash, extension=content_type, is_private=True ) exam_face = UserOnlineExamFace.objects.create( user=self.user, online_exam=self.user_online_exam.online_exam, user_online_exam=self.user_online_exam, face=upload, face_type=UserOnlineExamFace.FACE_TYPE_IDENTITY ) if self.user_online_exam.status == UserOnlineExam.STATUS_WAIT: self.user_online_exam.identity_face = exam_face self.user_online_exam.status = UserOnlineExam.STATUS_UNDERWAY self.user_online_exam.start_at = timezone.now() self.user_online_exam.save() async_validate_examinee_id_face.delay(exam_face.id) class ExamineeCaptureForm(forms.Form): image = forms.CharField(required=True) def __init__(self, user, *args, **kwargs): self.user = user super(ExamineeCaptureForm, self).__init__(*args, **kwargs) def clean_image(self): image = self.cleaned_data.get('image') if image: if len(image) > (6 * 1 << 20): raise ValidationError('文件大小超过限制') if not image.startswith('data:image/'): raise ValidationError('图片格式错误, 格式应类似于: data:image/jpeg;base64,/9j/4AA....') return image