ソースを参照

模拟考试,下一题

wushaodong 3 年 前
コミット
482c59305d

+ 1 - 1
apps/api/staff/mock/urls.py

@@ -10,5 +10,5 @@ urlpatterns = [
 
 router = SimpleRouter()
 router.register(r'exam_paper', ExamPaperViewSet)
-# router.register(r'exam', ExamLogViewSet)
+router.register(r'exam_log', ExamLogViewSet)
 urlpatterns += router.urls

+ 220 - 7
apps/api/staff/mock/views.py

@@ -1,12 +1,12 @@
 # coding=utf-8
 import json
 import traceback
-from django.db.models import Sum, F
+from django.utils import timezone
 from rest_framework.decorators import action
 from rest_framework.serializers import ValidationError
 from rest_framework.views import APIView
 from django.db import transaction
-from django.db.models import Q
+from django.db.models import Q, Sum, F
 from utils.custom_modelviewset import CustomModelViewSet
 from utils import response_ok, response_error
 from utils.permission import IsAdministrator, IsStaff
@@ -15,27 +15,240 @@ from apps.examination.exam.filters import *
 from apps.system.models import SysLog
 from apps.foundation.serializers import SubjectSerializer, ChapterSerializer, SubjectSimpleSerializer, \
     ChapterSimpleSerializer, Subject
-from apps.examination.exampaper.filters import ExamPaper, ExamPaperFilter
+from apps.examination.exam.models import ExamAnswerLog, ExamAnswerOptionLog, ExamAnswerFillLog
+from apps.examination.exampaper.models import ExamPaper, ExamPaperDetail, ExamQuestion
+from apps.examination.exampaper.filters import ExamPaperFilter
 from apps.examination.exampaper.serializers import StaffExamPaperSerializer
+from apps.examination.examquestion.models import ExamQuestionOption, ExamQuestionFill
 
 class ExamPaperViewSet(CustomModelViewSet):
     permission_classes = [IsStaff, ]
-    queryset = ExamPaper.objects.filter(delete=False)
+    queryset = ExamPaper.objects.filter(delete=False, type=ExamPaper.MOCK)
     serializer_class = StaffExamPaperSerializer
 
     def filter_queryset(self, queryset):
         f = ExamPaperFilter(self.request.GET, queryset=queryset, request=self.request)
         return f.qs
 
+
 class ExamLogViewSet(CustomModelViewSet):
     permission_classes = [IsStaff, ]
     queryset = ExamLog.objects.filter(delete=False)
     serializer_class = StaffExamLogSerializer
 
     def filter_queryset(self, queryset):
-        # queryset = queryset.filter(user=self.request.user)
-        f = FormalExamLogFilter(self.request.GET, queryset=queryset)
-        return f.qs
+        queryset = queryset.filter(user=self.request.user)
+        return queryset
+
+    def create(self, request, *args, **kwargs):
+        exampaper_id = request.data.get('exampaper')
+
+        try:
+            with transaction.atomic():
+                exampaper = ExamPaper.getById(exampaper_id)
+                data = {
+                    'subject': exampaper.subject.id,
+                    'type': ExamPaper.MOCK,
+                    'exampaper': exampaper_id,
+                    'user': request.user.id,
+                    'exam_time': timezone.now()
+                }
+                serializer = StaffExamLogSerializer(data=data)
+                if serializer.is_valid(raise_exception=True):
+                    instance = serializer.save()
+                    result = {
+                        'exam_log': instance.id,  # 模拟考试 id
+                    }
+                    return response_ok(result)
+        except ValidationError as e:
+            traceback.print_exc()
+            return response_error('数据格式有误')
+
+    @action(methods=['post'], detail=True)
+    def get_next_practise(self, request, pk):
+        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()
+                # 点击下一题,保存、判断当前习题答案
+                if now_practise:
+                    detail = ExamPaperDetail.objects.filter(id=now_practise).first()
+                    if not detail:
+                        raise CustomError('提交的考试习题有误,请刷新重试!')
+                    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:
+                            # 多选
+                            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):
+                                answer_log.status = ExamAnswerLog.RIGHT
+                            else:
+                                answer_log.status = ExamAnswerLog.WRONG
+                        answer_log.save()
+                    else:
+                        try:
+                            answer_log = ExamAnswerLog.objects.get(main=instance, question=now_question, )
+                            ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
+                            ExamAnswerFillLog.objects.filter(main=answer_log).delete()
+                            answer_log.status = None
+                            answer_log.save()
+                        except ExamAnswerLog.DoesNotExist:
+                            # traceback.print_exc()
+                            pass
+
+                question_data = {}
+                # 返回下一题
+                if next_practise:
+                    detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper, delete=False).first()
+                else:
+                    detail = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).first()
+
+                if detail:
+                    question = detail.question
+                    question_data = {
+                        'id': detail.id,
+                        'title': question.title,
+                        'next_type': question.type,  # 下一题习题类别
+                        'next_number': detail.order + 1,  # 下下一题序号,
+                        'option': [],
+                    }
+
+                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=detail).first()
+                    if question.type == ExamQuestion.JUDGMENT:
+                        item1 = {
+                            'id': 1,
+                            'content': '正确',
+                            'answer': True if answer_log and answer_log.status == ExamAnswerLog.RIGHT else False
+                        }
+                        item0 = {
+                            'id': 0,
+                            'content': '错误',
+                            'answer': True if answer_log and answer_log.status == ExamAnswerLog.WRONG else False
+                        }
+                        question_data['option'].append(item1)
+                        question_data['option'].append(item0)
+                    elif question.type <= ExamQuestion.MULTIPLE:
+                        rows = ExamQuestionOption.objects.filter(main=question, delete=False)
+                        for row in rows:
+                            option_log = ExamAnswerOptionLog.objects.filter(main=answer_log, option=row).first()
+                            item = {
+                                'id': row.id,
+                                'content': row.content,
+                                'answer': option_log and True or False
+                            }
+                            question_data['option'].append(item)
+                    elif question.type == ExamQuestion.FILL:
+                        rows = ExamQuestionFill.objects.filter(main=question, delete=False)
+                        for row in rows:
+                            option_log = ExamAnswerFillLog.objects.filter(main=answer_log, order=row.order).first()
+                            item = {
+                                'id': row.order,  # 填空题序号
+                                'content': option_log and option_log.content or '',
+                            }
+                            question_data['option'].append(item)
+
+                # 右侧习题类别列表
+                # 单选、多选、填空。选择答案后,可能会把答案清空,得加上NOTDONE过滤
+                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)
+                    single_questions_list.append(
+                        {
+                            'question_id': single,
+                            'complete': answer_log and True or False,
+                        }
+                    )
+                # 多选题
+                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)
+                    multiple_questions_list.append(
+                        {
+                            'question_id': multiple,
+                            'complete': answer_log and True or False,
+                        }
+                    )
+                # 填空题
+                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)
+                    fill_questions_list.append(
+                        {
+                            'question_id': fill,
+                            'complete': answer_log and True or False,
+                        }
+                    )
+                # 判断题
+                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)
+                    judgment_questions_list.append(
+                        {
+                            'question_id': judgment,
+                            'complete': answer_log and True or False,
+                        }
+                    )
+                result = {
+                    'question_data': question_data,  # 下一题练习题
+                    'single_questions_list': single_questions_list,  # 单选
+                    'multiple_questions_list': multiple_questions_list,  # 多选
+                    'fill_questions_list': fill_questions_list,  # 填空
+                    'judgment_questions_list': judgment_questions_list,  # 判断
+                }
+                return response_ok(result)
+        except CustomError as e:
+            return response_error(e.get_error_msg())
+        except Exception as e:
+            traceback.print_exc()
+            return response_error(str(e))
 
 class DictView(APIView):
     permission_classes = [IsStaff, ]

+ 1 - 1
apps/examination/exam/filters.py

@@ -20,4 +20,4 @@ class FormalExamLogFilter(django_filters.FilterSet):
 
     class Meta:
         model = ExamLog
-        fields = "__all__"
+        fields = "__all__"

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

@@ -61,6 +61,11 @@ class FormalExamLogSerializer(serializers.ModelSerializer):
         model = ExamLog
         fields = "__all__"
 
+class StaffExamLogSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = ExamLog
+        fields = "__all__"
 
 class ExamAnswerLogSerializer(serializers.ModelSerializer):
     item = serializers.SerializerMethodField()

+ 2 - 2
apps/examination/exampaper/serializers.py

@@ -90,8 +90,8 @@ class StaffExamPaperSerializer(serializers.ModelSerializer):
         from apps.examination.exam.models import ExamLog
         exampaper = ExamLog.objects.filter(user=self.context['request'].user,exampaper=obj)
         if exampaper:
-            return '做过'
-        return ''
+            return True
+        return False
 
     class Meta:
         model = ExamPaper