Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	apps/examination/exam/serializers.py
jiaweiqi 3 anni fa
parent
commit
1eb81b3c01

+ 94 - 71
apps/api/staff/mock/views.py

@@ -20,6 +20,8 @@ from apps.examination.exampaper.models import ExamPaper, ExamPaperDetail, ExamQu
 from apps.examination.exampaper.filters import ExamPaperFilter
 from apps.examination.exampaper.serializers import StaffExamPaperSerializer
 from apps.examination.examquestion.models import ExamQuestionOption, ExamQuestionFill
+from apps.practise.errorbook.models import ErrorBook
+
 
 class ExamPaperViewSet(CustomModelViewSet):
     permission_classes = [IsStaff, ]
@@ -40,6 +42,23 @@ class ExamLogViewSet(CustomModelViewSet):
         queryset = queryset.filter(user=self.request.user)
         return queryset
 
+    def retrieve(self, request, *args, **kwargs):
+        instance = self.get_object()
+        serializer = StaffExamLogRetrieveSerializer(instance)
+        answer_log = []
+        answer_logs = ExamAnswerLog.objects.filter(main=instance).order_by('detail__order')
+        for al in answer_logs:
+            item = {
+                'id':al.id,
+                'status':al.status,
+            }
+            answer_log.append(item)
+        result = {
+            'question': serializer.data,
+            'answer_log': answer_log,
+        }
+        return response_ok(result)
+
     def create(self, request, *args, **kwargs):
         exampaper_id = request.data.get('exampaper')
 
@@ -47,7 +66,6 @@ class ExamLogViewSet(CustomModelViewSet):
             with transaction.atomic():
                 exampaper = ExamPaper.getById(exampaper_id)
                 data = {
-                    'subject': exampaper.subject.id,
                     'type': ExamPaper.MOCK,
                     'exampaper': exampaper_id,
                     'user': request.user.id,
@@ -69,6 +87,7 @@ class ExamLogViewSet(CustomModelViewSet):
         now_practise = request.data.get('now_practise')  # 当前提交的模拟考试明细id。第一题或继续答题时,该参数为空
         answers = json.loads(request.data.get('answers'))  # 答案, 第一题或继续答题时,该参数为空
         next_practise = request.data.get('next_practise')  # 下一题id,首次加载第一题,传空
+
         try:
             with transaction.atomic():
                 instance = self.get_object()
@@ -80,60 +99,32 @@ class ExamLogViewSet(CustomModelViewSet):
                     now_question = detail.question
                     if len(answers) > 0:
                         answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance,
-                                                                                 detail=detail,)
-                        if now_question.type == ExamQuestion.SINGLE:
-                            # 单选
-                            ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
-                            answer = answers[0]
-                            ExamAnswerOptionLog.objects.create(main=answer_log, option_id=answer)
-                            right = ExamQuestionOption.objects.filter(main=now_question, id=answer, right=True,
-                                                                      delete=False)
-                            if right:
-                                answer_log.status = ExamAnswerLog.RIGHT
-                            else:
-                                answer_log.status = ExamAnswerLog.WRONG
-                        elif now_question.type == ExamQuestion.MULTIPLE:
-                            # 多选
+                                                                                 detail=detail, )
+                        if now_question.type <= ExamQuestion.MULTIPLE:
+                            # 单选、多选
                             answers.sort()
                             ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
                             for a in answers:
                                 ExamAnswerOptionLog.objects.create(main=answer_log, option_id=a)
-                            right = ExamQuestionOption.objects.filter(main=now_question, right=True,
-                                                                      delete=False).values_list('id', flat=True)
-                            list(right).sort()
-                            if answers == right:
-                                answer_log.status = ExamAnswerLog.RIGHT
-                            else:
-                                answer_log.status = ExamAnswerLog.WRONG
                         elif now_question.type == ExamQuestion.FILL:
                             # 填空
                             answers_len = len(answers)
-                            right = 1
                             ExamAnswerFillLog.objects.filter(main=answer_log).delete()
                             for a in range(0, answers_len):
                                 ExamAnswerFillLog.objects.create(main=answer_log, content=answers[a], order=a + 1)
-                                right_answer = ExamQuestionFill.objects.filter(main=now_question, content=answers[a],
-                                                                               order=a + 1)
-                                if not right_answer:
-                                    # 有一个填空错误,整题错误
-                                    right = 0
-                            if right:
-                                answer_log.status = ExamAnswerLog.RIGHT
-                            else:
-                                answer_log.status = ExamAnswerLog.WRONG
                         else:
                             # 判断
-                            if now_question.judgment == (answers[0] == 1):
+                            if answers[0] == 1:
                                 answer_log.status = ExamAnswerLog.RIGHT
                             else:
                                 answer_log.status = ExamAnswerLog.WRONG
-                        answer_log.save()
+                            answer_log.save()
                     else:
                         try:
-                            answer_log = ExamAnswerLog.objects.get(main=instance, question=now_question, )
+                            answer_log = ExamAnswerLog.objects.get(main=instance, detail=detail)
                             ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
                             ExamAnswerFillLog.objects.filter(main=answer_log).delete()
-                            answer_log.status = None
+                            answer_log.status = ExamAnswerLog.NOTDONE
                             answer_log.save()
                         except ExamAnswerLog.DoesNotExist:
                             # traceback.print_exc()
@@ -142,7 +133,8 @@ class ExamLogViewSet(CustomModelViewSet):
                 question_data = {}
                 # 返回下一题
                 if next_practise:
-                    detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper, delete=False).first()
+                    detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper,
+                                                            delete=False).first()
                 else:
                     detail = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).first()
 
@@ -192,11 +184,11 @@ class ExamLogViewSet(CustomModelViewSet):
 
                 # 右侧习题类别列表
                 # 单选、多选、填空。选择答案后,可能会把答案清空,得加上NOTDONE过滤
-                questions = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).values_list('id', flat=True)
+                questions = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).values_list('id',
+                                                                                                              flat=True)
                 single_questions_list = []
                 for single in questions.filter(question__type=ExamQuestion.SINGLE):
-                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=single).exclude(
-                        status=ExamAnswerLog.NOTDONE)
+                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=single)
                     single_questions_list.append(
                         {
                             'question_id': single,
@@ -206,8 +198,7 @@ class ExamLogViewSet(CustomModelViewSet):
                 # 多选题
                 multiple_questions_list = []
                 for multiple in questions.filter(question__type=ExamQuestion.MULTIPLE):
-                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=multiple).exclude(
-                        status=ExamAnswerLog.NOTDONE)
+                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=multiple)
                     multiple_questions_list.append(
                         {
                             'question_id': multiple,
@@ -217,8 +208,7 @@ class ExamLogViewSet(CustomModelViewSet):
                 # 填空题
                 fill_questions_list = []
                 for fill in questions.filter(question__type=ExamQuestion.FILL):
-                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=fill).exclude(
-                        status=ExamAnswerLog.NOTDONE)
+                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=fill)
                     fill_questions_list.append(
                         {
                             'question_id': fill,
@@ -228,8 +218,7 @@ class ExamLogViewSet(CustomModelViewSet):
                 # 判断题
                 judgment_questions_list = []
                 for judgment in questions.filter(question__type=ExamQuestion.JUDGMENT):
-                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=judgment).exclude(
-                        status=ExamAnswerLog.NOTDONE)
+                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=judgment)
                     judgment_questions_list.append(
                         {
                             'question_id': judgment,
@@ -257,51 +246,84 @@ class ExamLogViewSet(CustomModelViewSet):
             instance = self.get_object()
 
             with transaction.atomic():
-                answer_logs = ExamAnswerLog.objects.filter(main=instance)
-                for answer_log in answer_logs:
-                    question = answer_log.detail.question
+                paper_details = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False)
+                for detail in paper_details:
+                    # 创建模拟考试未答题记录,如果没有找到答案记录,则该题保留未答状态
+                    answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance, detail=detail)
+                    # answer_logs = ExamAnswerLog.objects.filter(main=instance)
+                    # for answer_log in answer_logs:
+                    question = detail.question
                     if question.type == ExamQuestion.SINGLE:
                         # 单选
                         answers = ExamAnswerOptionLog.objects.filter(main=answer_log).first()
                         if answers:
                             if answers.option.right:
                                 answer_log.status = ExamAnswerLog.RIGHT
+                                instance.single_answer_count += 1
                             else:
                                 answer_log.status = ExamAnswerLog.WRONG
+                                ErrorBook.add_error(question, request.user, answer_log)
                     elif question.type == ExamQuestion.MULTIPLE:
                         # 多选
-                        answers = ExamAnswerOptionLog.objects.filter(main=answer_log).order_by('option_id').values_list('option_id', flat=True)
-                        right = ExamQuestionOption.objects.filter(main=question, right=True,
-                                                                  delete=False).values_list('id', flat=True)
-                        if list(answers) == list(right):
-                            answer_log.status = ExamAnswerLog.RIGHT
-                        else:
-                            answer_log.status = ExamAnswerLog.WRONG
+                        answers = ExamAnswerOptionLog.objects.filter(main=answer_log).order_by('option_id').values_list(
+                            'option_id', flat=True)
+                        if answers:
+                            right = ExamQuestionOption.objects.filter(main=question, right=True,
+                                                                      delete=False).values_list('id', flat=True)
+                            if list(answers) == list(right):
+                                answer_log.status = ExamAnswerLog.RIGHT
+                                instance.multiple_answer_count += 1
+                            else:
+                                answer_log.status = ExamAnswerLog.WRONG
+                                ErrorBook.add_error(question, request.user, answer_log)
                     elif question.type == ExamQuestion.FILL:
                         # 填空
                         fill_logs = ExamAnswerFillLog.objects.filter(main=answer_log)
                         right = True
-                        for fill_log in fill_logs:
-                            right_answer = ExamQuestionFill.objects.filter(main=question, content=fill_log.content,
-                                                                           order=fill_log.order, delete=False)
-                            if not right_answer:
-                                right = False
-                                break
-                        if right:
-                            answer_log.status = ExamAnswerLog.RIGHT
-                        else:
-                            answer_log.status = ExamAnswerLog.WRONG
+                        if fill_logs:
+                            for fill_log in fill_logs:
+                                right_answer = ExamQuestionFill.objects.filter(main=question, content=fill_log.content,
+                                                                               order=fill_log.order, delete=False)
+                                if not right_answer:
+                                    right = False
+                                    break
+                            if right:
+                                answer_log.status = ExamAnswerLog.RIGHT
+                                instance.fill_answer_count += 1
+                            else:
+                                answer_log.status = ExamAnswerLog.WRONG
+                                ErrorBook.add_error(question, request.user, answer_log)
                     else:
                         # 判断
-                        if question.judgment == (answer_log.status == ExamAnswerLog.RIGHT):
-                            answer_log.status = ExamAnswerLog.RIGHT
-                        else:
-                            answer_log.status = ExamAnswerLog.WRONG
+                        if answer_log.status != ExamAnswerLog.NOTDONE:
+                            if question.judgment == (answer_log.status == ExamAnswerLog.RIGHT):
+                                answer_log.status = ExamAnswerLog.RIGHT
+                                instance.judgment_answer_count += 1
+                            else:
+                                answer_log.status = ExamAnswerLog.WRONG
+                                ErrorBook.add_error(question, request.user, answer_log)
                     answer_log.save()
 
                 instance.submit_time = timezone.now()
+                use_time = instance.exam_time - instance.submit_time
+                instance.use_time = use_time.seconds
+
+                single_answer_scores = instance.single_answer_count * instance.exampaper.single_scores
+                multiple_answer_scores = instance.multiple_answer_count * instance.exampaper.multiple_scores
+                fill_answer_scores = instance.fill_answer_count * instance.exampaper.fill_scores
+                judgment_answer_scores = instance.judgment_answer_count * instance.exampaper.judgment_scores
+
+                instance.single_answer_scores = single_answer_scores
+                instance.multiple_answer_scores = multiple_answer_scores
+                instance.fill_answer_scores = fill_answer_scores
+                instance.judgment_answer_scores = judgment_answer_scores
+                instance.scores = single_answer_scores + judgment_answer_scores + multiple_answer_scores + fill_answer_scores
                 instance.save()
-                SysLog.objects.addnew(request.user, SysLog.INSERT, u"提交模拟考试题答案,id=%d" % (instance.id))
+
+                instance.exampaper.did_count += 1
+                instance.exampaper.save()
+
+                SysLog.objects.addnew(request.user, SysLog.INSERT, u"提交模拟考试题,id=%d" % (instance.id))
         except CustomError as e:
             return response_error(e.get_error_msg())
         except Exception as e:
@@ -309,6 +331,7 @@ class ExamLogViewSet(CustomModelViewSet):
             return response_error(str(e))
         return response_ok()
 
+
 class DictView(APIView):
     permission_classes = [IsStaff, ]
 

+ 2 - 1
apps/examination/exam/models.py

@@ -107,6 +107,7 @@ class ExamLog(models.Model):
     multiple_answer_scores = models.IntegerField(verbose_name=u'多选题得分', default=0, editable=False)
     fill_answer_scores = models.IntegerField(verbose_name=u'填空题得分', default=0, editable=False)
     judgment_answer_scores = models.IntegerField(verbose_name=u'判断题得分', default=0, editable=False)
+
     single_answer_count = models.IntegerField(verbose_name=u'单选题答对数', default=0, editable=False)
     multiple_answer_count = models.IntegerField(verbose_name=u'多选题答对数', default=0, editable=False)
     fill_answer_count = models.IntegerField(verbose_name=u'填空题答对数', default=0, editable=False)
@@ -159,4 +160,4 @@ class ExamAnswerFillLog(models.Model):
         db_table = "exam_answer_fill_log"
         ordering = ['order', 'id']
         verbose_name = u"填空题回答"
-        default_permissions = ()
+        default_permissions = ()

+ 38 - 0
apps/examination/exam/serializers.py

@@ -5,6 +5,7 @@ from .models import Exam, ExamLog, ExamAnswerLog, ExamAnswerOptionLog, ExamAnswe
 from apps.examination.examquestion.models import ExamQuestion
 from utils.exceptions import CustomError
 
+
 class ExamSerializer(serializers.ModelSerializer):
     subject_name = serializers.CharField(source='subject.name', read_only=True)
     type_text = serializers.CharField(source='get_type_display', read_only=True)
@@ -41,6 +42,7 @@ class ExamSerializer(serializers.ModelSerializer):
         instance.save()
         return instance
 
+
 class FormalExamLogSerializer(serializers.ModelSerializer):
     exam_name = serializers.CharField(source='exam.name', read_only=True)
     exam_subject_name = serializers.CharField(source='exam.subject.name', read_only=True)
@@ -61,12 +63,48 @@ class FormalExamLogSerializer(serializers.ModelSerializer):
         model = ExamLog
         fields = "__all__"
 
+
 class StaffExamLogSerializer(serializers.ModelSerializer):
+    exampaper_name = serializers.CharField(source='exampaper.name', read_only=True)
+    right_count = serializers.SerializerMethodField()
+    wrong_count = serializers.SerializerMethodField()
+
+    class Meta:
+        model = ExamLog
+        fields = ('id', 'type', 'exampaper', 'user', 'exam_time', 'exampaper_name', 'exam_time', 'submit_time',
+                  'scores', 'right_count','wrong_count',)
+
+    def get_right_count(self, obj):
+        return obj.single_answer_count + obj.multiple_answer_count + obj.fill_answer_count +  obj.judgment_answer_count
+
+    def get_wrong_count(self, obj):
+        return obj.exampaper.question_total_count - (obj.single_answer_count + obj.multiple_answer_count + obj.fill_answer_count +  obj.judgment_answer_count)
+
+class StaffExamLogRetrieveSerializer(serializers.ModelSerializer):
+    exampaper_name = serializers.CharField(source='exampaper.name', read_only=True)
+    question_total_count = serializers.CharField(source='exampaper.question_total_count', read_only=True)
+    question_total_scores = serializers.CharField(source='exampaper.question_total_scores', read_only=True)
+
+    single_total_count = serializers.CharField(source='exampaper.single_total_count', read_only=True)
+    multiple_total_count = serializers.CharField(source='exampaper.multiple_total_count', read_only=True)
+    fill_total_count = serializers.CharField(source='exampaper.fill_total_count', read_only=True)
+    judgment_total_count = serializers.CharField(source='exampaper.judgment_total_count', read_only=True)
+
+    single_total_scores = serializers.CharField(source='exampaper.single_total_scores', read_only=True)
+    multiple_total_scores = serializers.CharField(source='exampaper.multiple_total_scores', read_only=True)
+    fill_total_scores = serializers.CharField(source='exampaper.fill_total_scores', read_only=True)
+    judgment_total_scores = serializers.CharField(source='exampaper.judgment_total_scores', read_only=True)
+
+    total_right_count = serializers.SerializerMethodField()
 
     class Meta:
         model = ExamLog
         fields = "__all__"
 
+    def get_total_right_count(self, obj):
+        return obj.single_answer_count + obj.multiple_answer_count + obj.fill_answer_count +  obj.judgment_answer_count
+
+
 class ExamAnswerLogSimpleSerializer(serializers.ModelSerializer):
     item = serializers.SerializerMethodField()
 

+ 4 - 1
apps/examination/exampaper/models.py

@@ -39,6 +39,7 @@ class ExamPaper(models.Model):
     multiple_hard_count = models.IntegerField(verbose_name=u'困难多选题数量', default=0)
     fill_hard_count = models.IntegerField(verbose_name=u'困难填空题数量', default=0)
     judgment_hard_count = models.IntegerField(verbose_name=u'困难判断题数量', default=0)
+
     single_scores = models.IntegerField(verbose_name=u'单选题单题分数', default=0)
     multiple_scores = models.IntegerField(verbose_name=u'多选题单题分数', default=0)
     fill_scores = models.IntegerField(verbose_name=u'填空题单题分数', default=0)
@@ -48,10 +49,12 @@ class ExamPaper(models.Model):
     multiple_total_count = models.IntegerField(verbose_name=u'多选题总数量', default=0, editable=False)
     fill_total_count = models.IntegerField(verbose_name=u'填空题总数量', default=0, editable=False)
     judgment_total_count = models.IntegerField(verbose_name=u'判断题总数量', default=0, editable=False)
+
     single_total_scores = models.IntegerField(verbose_name=u'单选题总分数', default=0, editable=False)
     multiple_total_scores = models.IntegerField(verbose_name=u'多选题总分数', default=0, editable=False)
     fill_total_scores = models.IntegerField(verbose_name=u'填空题总分数', default=0, editable=False)
     judgment_total_scores = models.IntegerField(verbose_name=u'判断题总分数', default=0, editable=False)
+
     question_total_count  = models.IntegerField(verbose_name=u'试题总数量', default=0, editable=False)
     question_total_scores = models.IntegerField(verbose_name=u'试题总分数', default=0, editable=False)
 
@@ -168,4 +171,4 @@ class ExamPaperDetail(models.Model):
         db_table = "exam_paper_detail"
         ordering = ['order']
         verbose_name = u"试卷明细"
-        default_permissions = ()
+        default_permissions = ()

+ 16 - 2
apps/practise/errorbook/models.py

@@ -1,5 +1,5 @@
 # coding=utf-8
-
+from django.db.models import F
 from django.db import models
 from django.utils import timezone
 from django.conf import settings
@@ -18,4 +18,18 @@ class ErrorBook(models.Model):
         db_table = "practise_error_book"
         ordering = ['-id']
         verbose_name = u"错题集"
-        default_permissions = ()
+        default_permissions = ()
+
+    @staticmethod
+    def add_error(question, user, answer_log):
+        '''
+        :param question: 试题对象
+        :param user: 用户对象
+        :param answer_log: 答题记录对象
+        :return:
+        '''
+        instance = ErrorBook.objects.filter(question=question, create_user=user)
+        if instance:
+            instance.update(last_answer_log=answer_log, wrong_count=F('wrong_count')+1, last_time=timezone.now())
+        else:
+            ErrorBook.objects.create(question=question, create_user=user, last_answer_log=answer_log, wrong_count=1)