基于django的试卷管理

Django是一个免费且开源的Python Web框架,它采用了MVC(Model-View-Controller)的软件架构模式,用于构建高效、安全、可扩展的 Web 应用程序。Django提供了大量的构建 Web 应用程序所需的功能,例如表单处理、认证、管理后台、数据库 ORM、URL路由等等,使得开发人员可以专注于业务逻辑的实现,大大提高了开发效率。同时,Django还具有高度的安全性和可维护性,因此广泛地应用于各种规模的 Web 项目中,包括知名的网站和应用程序,如Instagram、Pinterest、Mozilla等等。

这是一个单独的板块,新建app,在settings里进行注册

先上模型

from django.contrib.auth.models import User
from django.db import models
from utils.modelsMixin import ModelSetMixin
# Create your models here.
class Label(models.Model):
    name = models.CharField(max_length=30, verbose_name='标签名', unique=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        db_table = 'label'
        verbose_name = '标签'
        verbose_name_plural = verbose_name

class Topic(ModelSetMixin):
    TYPE_CHOICES = (
        (0, '单选题'),
        (1, '多选题'),
        (2, '判断题'),
        (3, '填空题'),
        (4, '问答题'),
    )
    subject = models.TextField(verbose_name='题干')
    type = models.IntegerField(verbose_name='类型', choices=TYPE_CHOICES)
    score = models.FloatField(verbose_name='分值', default=1.0, null=True, blank=True)
    answer = models.TextField(verbose_name='答案')

    label = models.ForeignKey(Label, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        db_table = 'topic'
        verbose_name = '题目'
        verbose_name_plural = verbose_name

Label 模型类有两个字段:name 和 user。name 是一个 CharField,表示标签名,最大长度为 30,且必须唯一。user 是一个 ForeignKey,表示标签所属的用户,当用户被删除时,与之关联的标签也会被删除。 Topic 模型类有七个字段:subject、type、score、answer、label、user 和 created_time。subject 是一个 TextField,表示题干。type 是一个 IntegerField,表示题目类型,有五种选择。score 是一个 FloatField,表示分值,默认为 1.0,可以为空。answer 是一个 TextField,表示答案。label 是一个 ForeignKey,表示题目所属的标签,当标签被删除时,与之关联的题目也会被删除。user 是一个 ForeignKey,表示题目所属的用户,当用户被删除时,与之关联的题目也会被删除。created_time 是一个 DateTimeField,表示题目创建时间,使用了一个自定义的 Mixin 类 ModelSetMixin 来自动设置创建时间和更新时间。 这些模型类的 Meta 类中定义了数据库表名、verbose_name 和 verbose_name_plural。

编写序列化器,先将所有字段进行返回

from rest_framework.serializers import ModelSerializer

from work.models import *


class LabelSerializer(ModelSerializer):
    class Meta:
        model = Label
        fields = '__all__'

在视图里增加必要的权限,可以新建py文件定义权限装饰器,用于区分老师和学生。区别在于答案的显示与否。在这里用于调用。调用@action可以自动生成路由。

其中分页器采用limit分页器。用于指定跳转。

from random import sample

from django.db.models import Q
from django.shortcuts import render

# Create your views here.
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from utils.permission import *
from work.serializers import *
from rest_framework.pagination import LimitOffsetPagination


class TopicPaginationLimitOffset(LimitOffsetPagination):
    default_limit = 3
    max_limit = 100

class LabelViewSet(ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Label.objects.all()
    serializer_class = LabelSerializer

    @wrap_permission(TeacherPermission)
    @auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(RootPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

class TopicViewSet(ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Topic.objects.filter(is_delete=False)
    serializer_class = TopicSerializer
    # pagination_class = TopicPaginationPageNumber
    pagination_class = TopicPaginationLimitOffset

    def get_queryset(self):
        if self.action in ['practice', 'random']:
            return Topic.objects.filter(Q(is_delete=False) & ~Q(label__name__contains='试卷'))
        return self.queryset

    def get_serializer(self, *args, **kwargs):
        if self.action in ['exam', 'random']:
            return TopicStudentSerializer(*args, **kwargs)
        return self.serializer_class(*args, **kwargs)

    @wrap_permission(TeacherPermission)
    def list(self, request, *args, **kwargs):#查多个
        return ModelViewSet.list(self, request, *args, **kwargs)\

    @wrap_permission(TeacherPermission)
    def retrieve(self, request, *args, **kwargs):#查单一
        return ModelViewSet.retrieve(self, request, *args, **kwargs)

    @wrap_permission(TeacherPermission)
    @auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(RootPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

    @action(methods=['get'], detail=False)
    def practice(self, request):
        return ModelViewSet.list(self, request)

    @action(methods=['get'], detail=True)
    def exam(self, request, pk):
        #获取指定标签,指定试卷
        labels = Label.objects.filter(id=pk, name__contains='试卷').first()
        #判断有没有这个试卷,没有返回404
        if not labels:
            return Response(status=HTTP_404_NOT_FOUND)
        #有,则获取这个试卷的所有题目,不包含答案,通过管理器,题目_ser
        topics = labels.topic_set.filter(is_delete=False)
        serializer = self.get_serializer(topics, many=True)
        return Response(serializer.data)

    @action(methods=['get'], detail=False)
    def random(self, request):
        #获取随机刷题个数
        try:
            size = int(request.query_params.get('size', 3))
        except ValueError:
            return Response(status=HTTP_400_BAD_REQUEST)
        #获取查寻集,随机抽取指定个数
        pool = list(self.get_queryset())
        #判断要获取的随机题目个数是否超过题目总数,如果操作,则会给出提示
        if len(pool) < size:
            return Response({'detail':'超出题目个数:题目总数为: %s' % len(pool)}, status=HTTP_400_BAD_REQUEST)
        #序列化进行返回
        serializer = self.get_serializer(sample(pool, size), many=True)
        return Response(serializer.data)

优化序列化器

from rest_framework.serializers import *
from rest_framework import serializers

from work.models import *


class LabelSerializer(ModelSerializer):

    username = serializers.CharField(source='user.username', read_only=True)
    class Meta:
        model = Label
        fields = '__all__'
        extra_kwargs = {
            'user': {'required': False, 'write_only': True}
        }

class TopicSerializer(ModelSerializer):
    label_name = serializers.CharField(source='label.name', read_only=True)
    user_name = serializers.CharField(source='user.username', read_only=True)
    class Meta:
        model = Topic
        exclude = ['is_delete']


class TopicStudentSerializer(ModelSerializer):
    label_name = serializers.CharField(source='label.name', read_only=True)
    user_name = serializers.CharField(source='user.username', read_only=True)
    class Meta:
        model = Topic
        exclude = ['is_delete', 'answer']

这段代码是用于序列化 Django 模型的,使用了 Django REST framework 库中的 serializers 模块。其中包含了三个序列化器:

1. LabelSerializer:用于序列化 Label 模型,将其转换为 JSON 格式。其中,username 字段是通过 user 模型中的 username 字段来获取的,且只读。extra_kwargs 中的设置表示 user 字段不是必须的,且只能在写入时使用。

2. TopicSerializer:用于序列化 Topic 模型,将其转换为 JSON 格式。其中,label_name 和 user_name 字段是通过 label 和 user 模型中的 name 和 username 字段来获取的,且只读。exclude 中的设置表示排除 is_delete 字段。

3. TopicStudentSerializer:与 TopicSerializer 类似,但是排除了 answer 字段。

采用路由器

from rest_framework.routers import DefaultRouter
from work.views import *
urlpatterns = []
router = DefaultRouter()
router.register('label', LabelViewSet),
router.register('topics', TopicViewSet),
urlpatterns += router.urls

它自带测试页面,输入IP+接口进行测试。一切正常。OK

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值