# coding=utf-8 import json import traceback from django.db.models import Sum, F from rest_framework.decorators import action from rest_framework.views import APIView from django.db import transaction from rest_framework.viewsets import ReadOnlyModelViewSet from django.db.models import Q from utils.custom_modelviewset import CustomModelViewSet from utils import response_ok, response_error from utils.permission import IsAdministrator from utils.format import ExcelImporter from apps.examination.examquestion.serializers import * from apps.examination.examquestion.filters import * from apps.system.models import SysLog from apps.foundation.models import Subject, Chapter class ExamQuestionViewSet(CustomModelViewSet): permission_classes = [IsAdministrator, ] queryset = ExamQuestion.objects.filter(delete=False) serializer_class = ExamQuestionSerializer def filter_queryset(self, queryset): queryset = queryset.filter() f = ExamQuestionFilter(self.request.GET, queryset=queryset) return f.qs def perform_create(self, serializer): super(ExamQuestionViewSet, self).perform_create(serializer) instance = serializer.instance validated_data = serializer.validated_data SysLog.objects.addnew(self.request.user, SysLog.INSERT, u'添加试题库试题,id=%d' % (instance.id), validated_data) def perform_update(self, serializer): super(ExamQuestionViewSet, self).perform_update(serializer) instance = serializer.instance validated_data = serializer.validated_data SysLog.objects.addnew(self.request.user, SysLog.UPDATE, u'修改试题库试题,id=%d' % (instance.id), validated_data) if 'feedback' in self.request.data and self.request.data['feedback']: feedback = ExamQuestionFeedback.getById(self.request.data['feedback']) feedback.process(self.request.user) feedback.save() SysLog.objects.addnew(self.request.user, SysLog.UPDATE, u'处理试题错误反馈,id=%d' % (feedback.id)) def destroy(self, request, *args, **kwargs): with transaction.atomic(): instance = self.get_object() instance.delete = True instance.save() SysLog.objects.addnew(request.user, SysLog.INSERT, u"删除试题库试题,id=%d" % instance.id) return response_ok() @action(methods=['post'], detail=False) def import_single(self, request): file = request.FILES.get('excel_file') status = ExcelImporter.validity(file) if not status['success']: return response_error(status['errors']) data = status['data'] question_count = 0 line = 2 try: with transaction.atomic(): cur_question = None for row in data: title = row['试题内容'] subject = row['科目'] chapter = row['章节'] difficulty_text = row['难度'] scores= row['分数'] analysis = row['解析'] content = row['选项'] right = row['正确答案'] if title and content: raise CustomError(u'第%d行:数据格式不正确' % line) if title and not content: if not subject: raise CustomError(u'第%d行:科目不能为空' % line) if not chapter: raise CustomError(u'第%d行:章节不能为空' % line) if not difficulty_text: raise CustomError(u'第%d行:难度不能为空' % line) if not scores: raise CustomError(u'第%d行:分数不能为空' % line) if difficulty_text == u'简单': difficulty = ExamQuestion.SIMPLE elif difficulty_text == u'中等': difficulty = ExamQuestion.MID elif difficulty_text == u'困难': difficulty = ExamQuestion.HARD else: raise CustomError(u'第%d行:难度为无效数据' % line) subject = Subject.objects.filter(name=subject, delete=False).first() if not subject: raise CustomError(u'第%d行:科目为无效数据' % line) chapter = Chapter.objects.filter(subject=subject, name=chapter, delete=False).first() if not chapter: raise CustomError(u'第%d行:章节为无效数据' % line) try: scores = int(scores) except: raise CustomError(u'第%d行:分数为无效数据' % line) cur_question = ExamQuestion.objects.create( chapter=chapter, type=ExamQuestion.SINGLE, difficulty=difficulty, scores=scores, title=title, analysis=analysis, create_user=request.user, create_time=timezone.now() ) question_count += 1 if content and not title: if not cur_question: continue if right: ExamQuestionOption.objects.create(main=cur_question, content=content, right=True) else: ExamQuestionOption.objects.create(main=cur_question, content=content) line += 1 SysLog.objects.addnew(request.user, SysLog.IMPORT, u"导入[%d]道单选题" % (question_count)) except CustomError as e: return response_error(e.get_error_msg()) except Exception as e: traceback.print_exc() return response_error(str(e)) return response_ok() @action(methods=['post'], detail=False) def import_multiple(self, request): file = request.FILES.get('excel_file') status = ExcelImporter.validity(file) if not status['success']: return response_error(status['errors']) data = status['data'] question_count = 0 line = 2 try: with transaction.atomic(): cur_question = None for row in data: title = row['试题内容'] subject = row['科目'] chapter = row['章节'] difficulty_text = row['难度'] scores = row['分数'] analysis = row['解析'] content = row['选项'] right = row['正确答案'] if title and content: raise CustomError(u'第%d行:数据格式不正确' % line) if title and not content: if not subject: raise CustomError(u'第%d行:科目不能为空' % line) if not chapter: raise CustomError(u'第%d行:章节不能为空' % line) if not difficulty_text: raise CustomError(u'第%d行:难度不能为空' % line) if not scores: raise CustomError(u'第%d行:分数不能为空' % line) if difficulty_text == u'简单': difficulty = ExamQuestion.SIMPLE elif difficulty_text == u'中等': difficulty = ExamQuestion.MID elif difficulty_text == u'困难': difficulty = ExamQuestion.HARD else: raise CustomError(u'第%d行:难度为无效数据' % line) subject = Subject.objects.filter(name=subject, delete=False).first() if not subject: raise CustomError(u'第%d行:科目为无效数据' % line) chapter = Chapter.objects.filter(subject=subject, name=chapter, delete=False).first() if not chapter: raise CustomError(u'第%d行:章节为无效数据' % line) try: scores = int(scores) except: raise CustomError(u'第%d行:分数为无效数据' % line) cur_question = ExamQuestion.objects.create( chapter=chapter, type=ExamQuestion.MULTIPLE, difficulty=difficulty, scores=scores, title=title, analysis=analysis, create_user=request.user, create_time=timezone.now() ) question_count += 1 if content and not title: if not cur_question: continue if right: ExamQuestionOption.objects.create(main=cur_question, content=content, right=True) else: ExamQuestionOption.objects.create(main=cur_question, content=content) line += 1 SysLog.objects.addnew(request.user, SysLog.IMPORT, u"导入[%d]道多选题" % (question_count)) except CustomError as e: return response_error(e.get_error_msg()) except Exception as e: traceback.print_exc() return response_error(str(e)) return response_ok() @action(methods=['post'], detail=False) def import_fill(self, request): file = request.FILES.get('excel_file') status = ExcelImporter.validity(file) if not status['success']: return response_error(status['errors']) data = status['data'] question_count = 0 line = 2 try: with transaction.atomic(): cur_question = None order = 0 for row in data: title = row['试题内容'] subject = row['科目'] chapter = row['章节'] difficulty_text = row['难度'] scores = row['分数'] analysis = row['解析'] content = row['答案'] if title and not content: raise CustomError(u'第%d行:答案不能为空' % line) if title and content: if not subject: raise CustomError(u'第%d行:科目不能为空' % line) if not chapter: raise CustomError(u'第%d行:章节不能为空' % line) if not difficulty_text: raise CustomError(u'第%d行:难度不能为空' % line) if not scores: raise CustomError(u'第%d行:分数不能为空' % line) if difficulty_text == u'简单': difficulty = ExamQuestion.SIMPLE elif difficulty_text == u'中等': difficulty = ExamQuestion.MID elif difficulty_text == u'困难': difficulty = ExamQuestion.HARD else: raise CustomError(u'第%d行:难度为无效数据' % line) subject = Subject.objects.filter(name=subject, delete=False).first() if not subject: raise CustomError(u'第%d行:科目为无效数据' % line) chapter = Chapter.objects.filter(subject=subject, name=chapter, delete=False).first() if not chapter: raise CustomError(u'第%d行:章节为无效数据' % line) try: scores = int(scores) except: raise CustomError(u'第%d行:分数为无效数据' % line) order = 1 cur_question = ExamQuestion.objects.create( chapter=chapter, type=ExamQuestion.FILL, difficulty=difficulty, scores=scores, title=title, analysis=analysis, create_user=request.user, create_time=timezone.now() ) ExamQuestionFill.objects.create(main=cur_question, content=content, order=order) question_count += 1 order += 1 if content and not title: if (not cur_question) or (not order): continue ExamQuestionFill.objects.create(main=cur_question, content=content, order=order) order += 1 line += 1 SysLog.objects.addnew(request.user, SysLog.IMPORT, u"导入[%d]道填空题" % (question_count)) except CustomError as e: return response_error(e.get_error_msg()) except Exception as e: traceback.print_exc() return response_error(str(e)) return response_ok() @action(methods=['post'], detail=False) def import_judgment(self, request): file = request.FILES.get('excel_file') status = ExcelImporter.validity(file) if not status['success']: return response_error(status['errors']) data = status['data'] line = 2 try: with transaction.atomic(): for row in data: title = row['试题内容'] subject = row['科目'] chapter = row['章节'] difficulty_text = row['难度'] scores = row['分数'] analysis = row['解析'] judgment_text = row['答案'] if not title: raise CustomError(u'第%d行:试题内容不能为空' % line) if not subject: raise CustomError(u'第%d行:科目不能为空' % line) if not chapter: raise CustomError(u'第%d行:章节不能为空' % line) if not difficulty_text: raise CustomError(u'第%d行:难度不能为空' % line) if not scores: raise CustomError(u'第%d行:分数不能为空' % line) if not judgment_text: raise CustomError(u'第%d行:答案不能为空' % line) if difficulty_text == u'简单': difficulty = ExamQuestion.SIMPLE elif difficulty_text == u'中等': difficulty = ExamQuestion.MID elif difficulty_text == u'困难': difficulty = ExamQuestion.HARD else: raise CustomError(u'第%d行:难度为无效数据' % line) if judgment_text == u'正确': judgment = True elif judgment_text == u'错误': judgment = False else: raise CustomError(u'第%d行:答案为无效数据' % line) subject = Subject.objects.filter(name=subject, delete=False).first() if not subject: raise CustomError(u'第%d行:科目为无效数据' % line) chapter = Chapter.objects.filter(subject=subject, name=chapter, delete=False).first() if not chapter: raise CustomError(u'第%d行:章节为无效数据' % line) try: scores = int(scores) except: raise CustomError(u'第%d行:分数为无效数据' % line) ExamQuestion.objects.create( chapter=chapter, type=ExamQuestion.JUDGMENT, difficulty=difficulty, scores=scores, title=title, judgment=judgment, analysis=analysis, create_user=request.user, create_time=timezone.now() ) line += 1 SysLog.objects.addnew(request.user, SysLog.IMPORT, u"导入[%d]道判断题" % (line - 2)) except CustomError as e: return response_error(e.get_error_msg()) except Exception as e: traceback.print_exc() return response_error(str(e)) return response_ok() class ExamQuestionFeedbackViewSet(ReadOnlyModelViewSet): permission_classes = [IsAdministrator, ] queryset = ExamQuestionFeedback.objects.filter().order_by('status', '-id') serializer_class = ExamQuestionFeedbackSerializer def filter_queryset(self, queryset): f = ExamQuestionFeedbackFilter(self.request.GET, queryset=queryset) return f.qs