161 lines
5.8 KiB
Python
161 lines
5.8 KiB
Python
from apps.utils.serializers import CustomModelSerializer
|
|
from rest_framework import serializers
|
|
from .models import Questioncat, Question, Paper, PaperQuestion, Exam, ExamRecord, AnswerDetail
|
|
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
|
|
from django.db import transaction
|
|
|
|
class QuestioncatSerializer(CustomModelSerializer):
|
|
class Meta:
|
|
model = Questioncat
|
|
fields = '__all__'
|
|
|
|
class QuestionSerializer(CustomModelSerializer):
|
|
class Meta:
|
|
model = Question
|
|
fields = '__all__'
|
|
|
|
class PaperQuestionSerializer(CustomModelSerializer):
|
|
class Meta:
|
|
model = PaperQuestion
|
|
fields = '__all__'
|
|
read_only_fields = EXCLUDE_FIELDS_BASE
|
|
|
|
|
|
class PaperListSerializer(CustomModelSerializer):
|
|
class Meta:
|
|
model = Paper
|
|
exclude = ["questions"]
|
|
|
|
class PaperPatchSerializer(CustomModelSerializer):
|
|
class Meta:
|
|
model = Paper
|
|
fields = ["name"]
|
|
|
|
class PaperSerializer(CustomModelSerializer):
|
|
detail = PaperQuestionSerializer(many=True)
|
|
class Meta:
|
|
model = Paper
|
|
exclude = ["questions"]
|
|
read_only_fields = ["editable"] + EXCLUDE_FIELDS
|
|
|
|
def create(self, validated_data):
|
|
detail = validated_data.pop("detail", [])
|
|
with transaction.atomic():
|
|
paper = super().create(validated_data)
|
|
qs = [PaperQuestion(paper=paper, question=item["question"], total_score=item["total_score"], sort=item["sort"]) for item in detail]
|
|
PaperQuestion.objects.bulk_create(qs)
|
|
return paper
|
|
|
|
def update(self, instance, validated_data):
|
|
detail = validated_data.pop("detail", [])
|
|
with transaction.atomic():
|
|
paper = super().update(instance, validated_data)
|
|
# 删除未有的数据
|
|
question_ids = [item["question"].id for item in detail]
|
|
PaperQuestion.objects.filter(paper=paper).exclude(question__id__in=question_ids).delete()
|
|
# 更新新数据
|
|
for item in detail:
|
|
PaperQuestion.objects.update_or_create(
|
|
paper=instance,
|
|
question=item["question"],
|
|
defaults={
|
|
"total_score": item["total_score"],
|
|
"sort": item["sort"]
|
|
}
|
|
)
|
|
return paper
|
|
|
|
def to_representation(self, instance):
|
|
representation = super().to_representation(instance)
|
|
detail_data = representation['detail']
|
|
sorted_detail_data = sorted(detail_data, key=lambda x: (x['sort'], x['create_time']))
|
|
representation['detail'] = sorted_detail_data
|
|
return sorted_detail_data
|
|
|
|
|
|
class ExamSerializer(CustomModelSerializer):
|
|
create_by_name = serializers.CharField(source='create_by.name', read_only=True)
|
|
paper = serializers.PrimaryKeyRelatedField(queryset=Paper.objects.all(), label='有考试记录,编辑时忽略')
|
|
class Meta:
|
|
model = Exam
|
|
fields = "__all__"
|
|
|
|
def update(self, instance, validated_data):
|
|
if ExamRecord.objects.filter(exam=instance).exists():
|
|
validated_data.pop("paper", None)
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
|
|
class AnswerDetailOutSerializer(CustomModelSerializer):
|
|
name = serializers.ReadOnlyField(source='question.name')
|
|
options = serializers.ReadOnlyField(source='question.options')
|
|
type = serializers.ReadOnlyField(source='question.type')
|
|
img = serializers.ReadOnlyField(source='question.img')
|
|
questioncat_name = serializers.ReadOnlyField(
|
|
source='question.questioncat.name')
|
|
level = serializers.ReadOnlyField(source='question.level')
|
|
|
|
class Meta:
|
|
model = AnswerDetail
|
|
fields = ['id', 'question', 'name', 'options', 'type', 'level',
|
|
'total_score', 'questioncat_name', 'img', 'user_answer', 'score', 'is_right']
|
|
|
|
|
|
class AnswerDetailSerializer(AnswerDetailOutSerializer):
|
|
right = serializers.ReadOnlyField(source='question.right')
|
|
class Meta:
|
|
model = AnswerDetail
|
|
fields = ['id', 'question', 'name', 'options', 'type', 'level', 'right',
|
|
'total_score', 'questioncat_name', 'img', 'user_answer', 'score', 'is_right']
|
|
|
|
class AnswerDetailUpdateSerializer(serializers.Serializer):
|
|
id = serializers.CharField(label='下发ID')
|
|
user_answer = serializers.JSONField(label='作答')
|
|
|
|
class ExamRecordInitSerizlier(CustomModelSerializer):
|
|
detail = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = ExamRecord
|
|
fields = ["id", "detail"]
|
|
|
|
def get_detail(self, obj):
|
|
objs = AnswerDetail.objects.select_related('question').filter(
|
|
examrecord=obj).order_by('id')
|
|
return AnswerDetailOutSerializer(instance=objs, many=True).data
|
|
|
|
|
|
class TookSerializerMixin:
|
|
took_format = serializers.SerializerMethodField()
|
|
|
|
def get_took_format(self, obj):
|
|
m, s = divmod(obj.took, 60)
|
|
h, m = divmod(m, 60)
|
|
return "%02d:%02d:%02d" % (h, m, s)
|
|
|
|
class ExamRecordSerializer(CustomModelSerializer, TookSerializerMixin):
|
|
create_by_name = serializers.CharField(source='create_by.name', read_only=True)
|
|
class Meta:
|
|
model = ExamRecord
|
|
exclude = ["questions"]
|
|
|
|
|
|
class ExamRecordDetailSerializer(ExamRecordSerializer, TookSerializerMixin):
|
|
detail = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = ExamRecord
|
|
fields = "__all__"
|
|
|
|
def get_detail(self, obj):
|
|
objs = AnswerDetail.objects.select_related('question').filter(
|
|
examrecord=obj).order_by('id')
|
|
return AnswerDetailSerializer(instance=objs, many=True).data
|
|
|
|
class ExamRecordSubmitSerializer(serializers.ModelSerializer):
|
|
detail = AnswerDetailUpdateSerializer(many=True)
|
|
|
|
class Meta:
|
|
model = ExamRecord
|
|
fields = ['detail'] |