自学内容网 自学内容网

实操学习——题目的管理


本文主要讲解题目的管理案例
1.题目的基本增删改查
2.题目的权限控制
3.题目的搜索

在这里插入图片描述

一、基础配置

  1. 创建一个名为work的app
    在这里插入图片描述

  2. 将work注册到settings.py
    在这里插入图片描述

  3. 在models.py中创建模型

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' #定义生成的mysql表名
        verbose_name = '标签'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name #重写__str__方法,返回标签名,这样在Topic模型中的label 字段显示为正常的标签名,而不是object

# 题目表
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)
    description = models.TextField(verbose_name='题目描述', 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:
        ordering = ['-update_time'] #可以在元信息中定义排序方式,倒序排序
        db_table = 'topic'
        verbose_name = '题目'
        verbose_name_plural = verbose_name

这里要导入自己创建的ModelSetMixin,代码如下:

from django.db import models


class DateTimeModelMixin(models.Model):
    """创建和修改时间模型拓展类"""
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        abstract = True  # 指定该类为抽象模型类,迁移映射的时候就不会创建对应的表,只是用于封装拓展


class IsDeleteModelMixin(models.Model):
    """逻辑删除模型拓展类"""
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    def delete(self, using=None, keep_parents=False):
        # 逻辑删除
        self.is_delete = True
        self.save()

    class Meta:
        abstract = True


class ModelSetMixin(DateTimeModelMixin, IsDeleteModelMixin):
    """模型拓展整合类"""

    class Meta:
        abstract = True

  1. 编写序列化器serializers.py
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *

# 有对应的模型可以直接继承ModelSerializer
class LabelSerializer(ModelSerializer):
#新增字段,查询时将username 也显示出来
    username = serializers.CharField(source='user.username', read_only=True)

    class Meta:
        model = Label
        fields = '__all__'

        extra_kwargs = {
        #将user设置为只写,查询时隐藏不显示user这个字段
            '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']

  1. 编写views.py视图函数
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 rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

from utils.permission import wrap_permisssion, TeacherPermission, RootPermission, auto_user, ActiveUserPermission
from .serializers import *

class LabelViewSet(ModelViewSet):
    queryset = Label.objects.all()
    serializer_class = LabelSerializer

class TopicViewSet(ModelViewSet):
    queryset = Topic.objects.filter(is_delete=False)
    serializer_class = TopicSerializer

  1. 编写路由urls.py
from rest_framework.routers import DefaultRouter

from .views import *

urlpatterns = []
router = DefaultRouter()
router.register('label', LabelViewSet)
router.register('topics', TopicViewSet)
urlpatterns += router.urls

7.配置总路由urls.py
在这里插入图片描述
8.启动测试
在这里插入图片描述

二、权限控制

  • 标签权限分析:

标签的权限:
创建:老师及以上
查看:登录可查看
修改:老师及以上
删除:超级管理员

设置最低基本权限:选择这个事物操作的最低权限,将最低权限定义为视图类的权限。最基础的就是登录。

  1. 修改视图views.py,增加权限
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 rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

from utils.permission import wrap_permisssion, TeacherPermission, RootPermission, auto_user, ActiveUserPermission
from .serializers import *

class LabelViewSet(ModelViewSet):
# 设置基础权限:该视图必须登录才能访问
    permission_classes = [IsAuthenticated]
    queryset = Label.objects.all()
    serializer_class = LabelSerializer

#重写create方法
@wrap_permisssion(TeacherPermission) #定义只有老师权限才可以创建
@auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)
    
    #重写create方法,操作的用户必须是当前登陆的用户
@wrap_permisssion(ActiveUserPermission)
@auto_user
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)
    
    #重写destroy方法,必须为超级管理员权限
    @wrap_permisssion(RootPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)
  1. 在permission.py中增加超级管理员的权限类RootPermission,以及其他权限如下。
from functools import update_wrapper

from django.contrib.auth.models import Group
from rest_framework.permissions import BasePermission 


class TeacherPermission(BasePermission):
    def has_permission(self, request, view):
        user = request.user  # 当前请求的用户信息
        # 判断身份,查询用户在不在老师这个分组里面
        group = Group.objects.filter(name='老师').first()
        user_groups = user.groups.all()
        return user.is_superuser or group in user_groups


class ActiveUserPermission(BasePermission):
    def has_permission(self, request, view):
        # 操作的用户必须是当前登陆的用户
        user = request.user
        return user.id == int(view.kwargs['pk'])

#超级管理员权限类
class RootPermission(BasePermission):
    def has_permission(self, request, view):
        user = request.user
        return user.is_superuser


# 更改权限装饰器
def wrap_permisssion(*permissions, validate_permisssion=True):
    def decorator(func):
        def wrapper(self, request, *args, **kwargs):
            self.permission_classes = permissions
            if validate_permisssion:
                self.check_permissions(request)
            return func(self, request, *args, **kwargs)

        return update_wrapper(wrapper, func)

    return decorator

#创建时自动原则对应的用户,而不是所有用户都能选择
def auto_user(func):
    def wrapper(self, request, *args, **kwargs):
        request.POST._mutable = True  # 让请求参数可以被修改,固定写法
        request.data['user'] = request.user.id #将user改为当前登录用户的id

        return func(self, request, *args, **kwargs) #返回原本函数执行的结果,即创建

    return wrapper

  • 题目操作权限分析

题目的权限:
创建:老师及以上
修改:自己
查看:
自带的查询包括答案,权限是老师
查询需要增加额外的接口,没有答案,权限是登录即可。防止被爬虫
删除:超级管理员

  1. 定义一个学生使用的序列化器TopicStudentSerializer,只能看到题目,无法查看到答案
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *

# 有对应的模型可以直接继承ModelSerializer
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'] #过滤掉答案
  1. 修改视图views.py,增加权限
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 rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

from utils.permission import wrap_permisssion, TeacherPermission, RootPermission, auto_user, ActiveUserPermission
from .serializers import *

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']: #判断当前的操作是否是exam或者random接口操作
            return TopicStudentSerializer(*args, **kwargs) #是的话返回学生使用的序列化器,不包含答案
        return self.serializer_class(*args, **kwargs) #不是的话直接返回serializer_class 

#重写查所有,只有老师可以查看带答案的数据
    @wrap_permisssion(TeacherPermission)
    def list(self, request, *args, **kwargs):
        return ModelViewSet.list(self, request, *args, **kwargs)
        
#重写查单一,只有老师可以查看带答案的数据
    @wrap_permisssion(TeacherPermission)
    def retrieve(self, request, *args, **kwargs):
        return ModelViewSet.retrieve(self, request, *args, **kwargs)

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

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

    @wrap_permisssion(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)
        # 有,则获取这个试卷的所有题目,不包含答案
        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)

三、分页

为什么要考虑到分页查询,这里我们假设数据库中有10万条题目,如果发起查询题目的请求,需要返回10万条数据,如果某个用户只需要练习20道题目,速度肯定会很慢,并且资源损耗严重。这时候就要考虑到使用分页。下面介绍DRF中使用的两种分页器

1. PageNumberPagination分页器

  1. 在views.py视图中定义分页器类
from rest_framework.pagination import PageNumberPagination
class TopicPaginationPageNumber(PageNumberPagination):
    page_size = 3  # 默认每页多少条,如果不传size,默认3条
    #page_size_param  = 'page' #定义传入页数的参数,默认为page
    page_size_query_param = 'size'  # 规定哪个参数为分页大小参数,参数可以自己定义,这里定义为size,则前端传入参数size = 10,每页展示10条,但是不会超过设置的最大每页条数100
    max_page_size = 100  # 最大每页多少条
  1. 在题目的视图类TopicViewSet中增加该分页属性
class TopicViewSet(ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Topic.objects.filter(is_delete=False)
    serializer_class = TopicSerializer
#分页器
    pagination_class = TopicPaginationPageNumber
  1. 发送查询请求。
    解释:
    使用分页器查询后,显示如下:
    count:总数
    next:下一页网址
    previous:上一页网址
    results:返回查询的结果集合
    如果需要指定返回条数,在前端传入size参数,指定每页展示条数
    在这里插入图片描述

2. LimitOffsetPagination分页器

  1. 在views.py视图中定义分页器类
from rest_framework.pagination import LimitOffsetPagination
class TopicPaginationLimitOffset(LimitOffsetPagination):
    default_limit = 3  # 默认每页多少条
    #limit_query_param = 'limit' #默认每页展示条数的参数为limit
    #offset_query_param = 'offset' #默认的偏移的参数为offset
    max_limit = 100  # 最大每页多少条


  1. 在题目的视图类TopicViewSet中增加该分页属性
class TopicViewSet(ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Topic.objects.filter(is_delete=False)
    serializer_class = TopicSerializer
#分页器
    pagination_class = TopicPaginationLimitOffset
  • 发送查询请求。
    返回的数据结构跟PageNumberPagination一样,只是网址中传入的参数区别
    在这里插入图片描述

3.总结

  • 使用PageNumberPagination的场景:
    固定点击下一页,再点击下一页
  • 使用LimitOffsetPagination的场景:
    固定点击下一页,再点击下一页。也可以实现跳转到指定题目,从指定题目开始。

四、题目操作模块

代码参考附件一

1. 考试

没有答案,需要提交答题结果,老师后台审核

  1. 在标签模型里可以添加试卷名标签
    在这里插入图片描述
  2. 在TopicViewSet视图中添加exam接口并将exam接口添加到重写 的get_serializer中,返回没有答案的数据。接口测试可以拿到数据
    在这里插入图片描述

2. 题目练习——顺序刷题

有答案,程序自动判定结果,也可以直接看答案

  1. 在TopicViewSet视图中添加practice接口,并重写queryset方法:修改使用’practice’接口时需要返回的数据集,不能查看到标签名包含试卷的题目,只能做练习题

3. 模拟考试

随机获取指定题目

  1. 在TopicViewSet视图中添加random接口,并在get_queryset和get_serializer中添加random接口
  2. 访问接口测试
    在这里插入图片描述

附件一:topic的视图函数

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 rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

from utils.permission import wrap_permisssion, TeacherPermission, RootPermission, auto_user, ActiveUserPermission
from .serializers import *


# class TopicPaginationPageNumber(PageNumberPagination):
#     page_size = 3  # 默认每页多少条
#     page_size_query_param = 'size'  # 规定哪个参数为分页大小参数 size = 10
#     max_page_size = 100  # 最大每页多少条

class TopicPaginationLimitOffset(LimitOffsetPagination):
    default_limit = 3  # 默认每页多少条
    max_limit = 100  # 最大每页多少条


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

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

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

    @wrap_permisssion(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

#重写queryset方法:修改使用'practice', 'random'接口时需要返回的数据集
    def get_queryset(self):
        if self.action in ['practice', 'random']:
            return Topic.objects.filter(Q(is_delete=False) & ~Q(label__name__contains='试卷')) #~Q(label__name__contains='试卷')标签名不包含”试卷“的数据
        return self.queryset

#重写serializer方法:修改使用'exam', 'random'接口时调用的序列化器
    def get_serializer(self, *args, **kwargs):
        if self.action in ['exam', 'random']:
            return TopicStudentSerializer(*args, **kwargs)
        return self.serializer_class(*args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def list(self, request, *args, **kwargs):
        return ModelViewSet.list(self, request, *args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def retrieve(self, request, *args, **kwargs):
        return ModelViewSet.retrieve(self, request, *args, **kwargs)

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

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

    @wrap_permisssion(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)

    #传入标签的id
    @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)
        # 有,则获取这个试卷的所有题目,不包含答案
        #.topic_set管理器获取到所有题目
        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:
        #request.query_params.get获取get请求传入的参数写法
        #没传入size,默认为3条
            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)

        # 序列化,返回
        #sample(pool, size)从pool中随机取size个数据进行序列化
        serializer = self.get_serializer(sample(pool, size), many=True)
        return Response(serializer.data)


补充:前端调用接口写法

在这里插入图片描述
前端完整代码:

<template>
    <div class="demo-collapse" v-loading="loading">
        <div>
            <div style="margin: 15px 0px">
                <el-input v-model="search" placeholder="请输入你要搜索内容" class="input-with-select">
                    <template #prepend>
                        <el-select v-model="select" placeholder="请选择" style="width: 110px">
                            <el-option label="题目内容" value="1"></el-option>
                        </el-select>
                    </template>
                    <template #append>
                        <el-button @click="searchfunc">
                            <el-icon>
                                <Search />
                            </el-icon>
                        </el-button>
                    </template>
                </el-input>
            </div>
            <div class="start">
                从第
                <el-input-number v-model="offset" :min="1" :max="topics.data.count" @change="get_topics" />题开始
            </div>
        </div>

        <el-collapse v-model="activeNames" v-infinite-scroll="load" infinite-scroll-disabled="disabled">
            <el-collapse-item v-for="(topic, index) in topics.data.results" :name="index" :key="topic.id">
                <template #title>
                    <span>{{ index + offset }}、</span>
                    <span v-html="topic.subject"></span>
                    <el-tag>{{ topic.label_name }}</el-tag>
                    <el-tag>{{ TYPE_CHOICES[topic.type] }}</el-tag>
                </template>
                <div v-html="topic.description"></div>
                <el-form :inline="true" class="demo-form-inline work">
                    <el-form-item label="作答">
                        <el-input v-model="topic.work_answer" placeholder="请填写你的答案"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="onSubmit(index)">提交</el-button>
                    </el-form-item>
                    <span v-if="topic.flag">{{ topic.flag }}、正确答案:{{ topic.answer }}</span>
                </el-form>
            </el-collapse-item>
            <el-empty :image-size="20" v-if="!topics.data.next" description="暂无更多题目"></el-empty>
        </el-collapse>
    </div>
</template>

<script>
import axios from 'axios'
import { reactive, ref } from 'vue-demi'
import { ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons'

export default {
    name: 'exercise',
    components: {
        Search
    },
    setup() {
        let loading = ref(true)
        let activeNames = ref([0])
        let search = ref('')
        let select = ref('1')
        const TYPE_CHOICES = ['单选题', '多选题', '判断题', '填空题', '问答题']

        let disabled = ref(false)

        let topics = reactive({
            data: {
                count: 0,
                next: null,
                previous: null,
                results: [
                    {
                        answer: "B",
                        create_time: "2021-11-19T20:25:56.885565",
                        description: "A、x = y = z = 1  \r<br/>B、x = (y = z + 1)\r<br/>C、x, y = y, x\r<br/>D、x  +=  y",
                        id: 1,
                        label: 1,
                        label_name: "python基础",
                        score: 1,
                        subject: "下列哪个语句在Python中是非法的",
                        type: 0,
                        update_time: "2021-11-19T20:25:56.885594",
                        user: 1,
                        user_name: "一个",
                    }
                ]
            }
        })

        let offset = ref(1)

        function get_topics(offset) {
            loading.value = true
            axios.get('/api/work/topics/practice/', {
                params: {
                    offset: offset - 1,
                    limit: 10
                },
                headers: {
                    'Authorization': 'JWT ' + (localStorage.getItem('token') ? localStorage.getItem('token') : sessionStorage.getItem('token'))
                }
            }).then(
                response => {
                    let results = []
                    response.data.results.forEach(e => {
                        e.description = e.description.replace(/\n/g, '<br/><br/>')
                        e.work_answer = ''
                        e.flag = null
                        results.push(e)
                    });
                    response.data.results = results
                    console.log(results)
                    topics.data = response.data
                    loading.value = false
                    disabled.value = false
                },
                error => {
                    console.log('请求失败', error.message)
                }
            )
        }
        get_topics(offset.value)
        function onSubmit(index) {
            let topic = topics.data.results[index]
            if (topic.answer.toUpperCase() == topic.work_answer.toUpperCase()) {
                topic.flag = '回答正确'
                ElMessage.success(topic.flag)
            } else {
                topic.flag = '回答错误'
                ElMessage.error(topic.flag)
            }
        }
        const load = () => {
            if (topics.data.next != null) {
                loading.value = true
                disabled.value = true
                let url = topics.data.next.replace('http://127.0.0.1:8000/', '/api/')
                axios.get(url, {
                    headers: {
                        'Authorization': 'JWT ' + (localStorage.getItem('token') ? localStorage.getItem('token') : sessionStorage.getItem('token'))
                    }
                }).then(
                    response => {
                        let results = []
                        response.data.results.forEach(e => {
                            e.description = e.description.replace(/\n/g, '<br/><br/>')
                            e.work_answer = ''
                            e.flag = null
                            results.push(e)
                        });
                        response.data.results = topics.data.results.concat(results);
                        topics.data = response.data
                        console.log(response.data)
                        loading.value = false
                        if (response.data.next == null) {
                            disabled.value = true
                        } else {
                            disabled.value = false
                        }
                    },
                    error => {
                        console.log('请求失败', error.message)
                    }
                )
            }
        }

        function searchfunc() {
            disabled.value = false
            axios.get('/api/work/topics/search/', {
                params: {
                    subject: search.value,
                },
                headers: {
                    'Authorization': 'JWT ' + (localStorage.getItem('token') ? localStorage.getItem('token') : sessionStorage.getItem('token'))
                }
            }).then(
                response => {
                    let results = []
                    response.data.results.forEach(e => {
                        e.description = e.description.replace(/\n/g, '<br/><br/>')
                        e.work_answer = ''
                        e.flag = null
                        results.push(e)
                    });
                    response.data.results = results
                    console.log(results)
                    topics.data = response.data
                    loading.value = false
                },
                error => {
                    console.log('请求失败', error.message)
                }
            )
        }
        return { topics, TYPE_CHOICES, loading, onSubmit, activeNames, offset, get_topics, load, disabled, search, select, searchfunc }
    }
}
</script>

<style scoped>
.el-tag {
    margin-left: 20px;
}

.work {
    margin-top: 20px;
}

.start {
    margin-bottom: 20px;
}
</style>

原文地址:https://blog.csdn.net/m0_51453764/article/details/142365505

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!