基于Django实现的智慧校园考试系统-自动组卷算法实现

目录

  • [一.🦁 项目概述](#一.🦁 项目概述)
    • [1.1 技术栈](#1.1 技术栈)
    • [1.2 安装与运行](#1.2 安装与运行)
  • [二.🦁 演示系统流程](#二.🦁 演示系统流程)
    • [2.1 管理员端](#2.1 管理员端)
    • [2.2 学生端](#2.2 学生端)
    • [2.3 自动组卷算法实现](#2.3 自动组卷算法实现)
      • [1. 核心思路](#1. 核心思路)
      • [2. 随机与去重](#2. 随机与去重)
  • [三.🦁 API接口文档](#三.🦁 API接口文档)
    • [3.1 用户管理](#3.1 用户管理)
    • [3.2 题库管理](#3.2 题库管理)
    • [3.3 考试管理](#3.3 考试管理)
    • [3.4 成绩管理](#3.4 成绩管理)

项目定制业务:前端、后端(Python、Java、C#、PHP)、算法(深度学习、机器学习)、大数据(Hadoop、hive、spark)、小程序等项目

无论是商用 还是学校项目(毕业设计、课程设计等) ,都可咨询,价格合理,服务周全!

如果你有需要,添加vx:732708009

一.🦁 项目概述

基于Django开发的智慧校园考试系统后端API,采用前后端分离架构,提供RESTful风格接口,涵盖用户管理、题库管理、考试管理和成绩管理等核心功能模块。首先,用户管理模块支持学生和管理员两种角色,提供用户注册与登录(JWT认证)、个人信息管理。其次,题库管理模块支持多种试题类型,如单选题、判断题、填空题、简答题,实现试题的CRUD操作、智能组卷算法、试题分类标签管理及难度系数设置。然后,考试管理模块涵盖考试创建、考生报名与审核、在线考试等功能,提供考试场次管理。最后,成绩管理模块实现了自动评分(客观题)、成绩统计分析、提供成绩查询、成绩分布可视化以及错题分析和历史成绩对比等功能。

1.1 技术栈

  • Python 3.8+
  • Django 4.2
  • Django REST Framework
  • MySQL

1.2 安装与运行

  1. 克隆项目:gitcodeGithup
  2. 安装依赖:pip install -r requirements.txt
  3. 配置数据库:修改settings.py中的数据库配置
  4. 运行服务器:python manage.py runserver

二.🦁 演示系统流程

2.1 管理员端

  1. 登录
  1. 仪表板

  2. 用户管理

  3. 题库管理

  4. 考试管理

  5. 试卷管理

  • 手动组卷
  • 自动组卷
  1. 成绩管理

2.2 学生端

  1. 首页
  2. 考试列表
  3. 查看成绩
  4. 个人中心
  5. 考试页面

2.3 自动组卷算法实现

1. 核心思路

  • 先创建一条考试记录 Exam (校验通过后保存)。
  • 对每个题型,分别按难度从题库查询题目列表。
  • 如果某个难度的题数不够,直接返回错误。
  • 若题数足够,就用 random.sample 在题目列表里随机抽取指定数量。
  • 把抽到的题目逐条保存成 ExamQuestion ,与该考试关联。
  • 最后返回这次考试的基本信息和总题数。

2. 随机与去重

  • random.sample 在同一题型+难度范围内不会重复抽同一题
  • 不会出现跨题型重复,因为查询条件包含 question_type
  • 如果 question_types 传入有重复值,会去重
python 复制代码
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def generate_exam_paper(request):
    # 获取考试基本信息
    exam_name = request.data.get('exam_name')
    start_time = request.data.get('start_time')
    end_time = request.data.get('end_time')
    duration = request.data.get('duration')
    
    # 获取题目配置
    easy_count = int(request.data.get('easy_count', 0))
    medium_count = int(request.data.get('medium_count', 0))
    hard_count = int(request.data.get('hard_count', 0))
    question_types = request.data.get('question_types', [])
    
    # 创建考试
    exam_data = {
        'exam_name': exam_name,
        'start_time': start_time,
        'end_time': end_time,
        'duration': duration
    }
    
    serializer = ExamSerializer(data=exam_data)
    if not serializer.is_valid():
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    exam = serializer.save()
    
    # 为每种题型按难度分布生成题目
    selected_questions = []
    total_questions = 0
    
    # 遍历每种题型
    for question_type in question_types:
        # 获取当前题型不同难度的题目
        easy_questions = list(Question.objects.filter(
            difficulty_level='easy', 
            question_type=question_type
        ))
        medium_questions = list(Question.objects.filter(
            difficulty_level='medium', 
            question_type=question_type
        ))
        hard_questions = list(Question.objects.filter(
            difficulty_level='hard', 
            question_type=question_type
        ))
        
        # 检查当前题型的题目数量是否足够
        if easy_count > 0 and len(easy_questions) < easy_count:
            return Response({
                "error": f"{question_type}类型的简单题目不足,需要 {easy_count} 道,实际只有 {len(easy_questions)} 道"
            }, status=status.HTTP_400_BAD_REQUEST)
        if medium_count > 0 and len(medium_questions) < medium_count:
            return Response({
                "error": f"{question_type}类型的中等题目不足,需要 {medium_count} 道,实际只有 {len(medium_questions)} 道"
            }, status=status.HTTP_400_BAD_REQUEST)
        if hard_count > 0 and len(hard_questions) < hard_count:
            return Response({
                "error": f"{question_type}类型的困难题目不足,需要 {hard_count} 道,实际只有 {len(hard_questions)} 道"
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # 为当前题型随机选择题目
        if easy_count > 0:
            selected_questions.extend(random.sample(easy_questions, easy_count))
            total_questions += easy_count
        if medium_count > 0:
            selected_questions.extend(random.sample(medium_questions, medium_count))
            total_questions += medium_count
        if hard_count > 0:
            selected_questions.extend(random.sample(hard_questions, hard_count))
            total_questions += hard_count
    
    # 添加题目到考试
    for question in selected_questions:
        ExamQuestion.objects.create(exam=exam, question=question)
    
    # 返回包含题目数量的考试信息
    exam_data = ExamSerializer(exam).data
    exam_data['question_count'] = total_questions
    
    return Response({
        "message": f"成功自动生成试卷,包含 {total_questions} 道题目(每种题型:简单{easy_count}道,中等{medium_count}道,困难{hard_count}道)",
        "exam": exam_data
    }, status=status.HTTP_201_CREATED)

三.🦁 API接口文档

3.1 用户管理

  1. 注册用户
  • URL: /api/users/register/

  • 方法: POST

  • 请求体:

    json 复制代码
    {
      "username": "用户名",
      "password": "密码",
      "role": "admin或student"
    }
  • 响应:

    json 复制代码
    {
      "user_id": 1,
      "username": "用户名",
      "role": "admin或student",
      "created_at": "创建时间"
    }
  1. 用户登录
  • URL: /api/users/login/

  • 方法: POST

  • 请求体:

    json 复制代码
    {
      "username": "用户名",
      "password": "密码"
    }
  • 响应:

    json 复制代码
    {
      "token": "JWT令牌",
      "user": {
        "user_id": 1,
        "username": "用户名",
        "role": "admin或student"
      }
    }
  1. 获取当前用户信息
  • URL: /api/users/current/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    {
      "user_id": 1,
      "username": "用户名",
      "role": "admin或student",
      "created_at": "创建时间"
    }
  1. 获取所有用户
  • URL: /api/users/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "user_id": 1,
        "username": "用户名",
        "role": "admin或student",
        "created_at": "创建时间"
      }
    ]
  1. 获取特定用户
  • URL: /api/users/{user_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    {
      "user_id": 1,
      "username": "用户名",
      "role": "admin或student",
      "created_at": "创建时间"
    }
  1. 更新用户
  • URL: /api/users/{user_id}/update/

  • 方法: PUT

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "username": "新用户名",
      "password": "新密码",
      "role": "新角色"
    }
  • 响应:

    json 复制代码
    {
      "user_id": 1,
      "username": "新用户名",
      "role": "新角色",
      "created_at": "创建时间"
    }
  1. 删除用户
  • URL: /api/users/{user_id}/delete/
  • 方法: DELETE
  • 请求头: Authorization: Bearer {token}
  • 响应: 204 No Content

3.2 题库管理

  1. 添加题目
  • URL: /api/questions/add/

  • 方法: POST

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "content": "题目内容",
      "question_type": "choice/true_false/fill_in_blank/essay",
      "difficulty_level": "easy/medium/hard"
    }
  • 响应:

    json 复制代码
    {
      "question_id": 1,
      "content": "题目内容",
      "question_type": "choice/true_false/fill_in_blank/essay",
      "difficulty_level": "easy/medium/hard",
      "created_at": "创建时间"
    }
  1. 获取所有题目
  • URL: /api/questions/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "question_id": 1,
        "content": "题目内容",
        "question_type": "choice/true_false/fill_in_blank/essay",
        "difficulty_level": "easy/medium/hard",
        "created_at": "创建时间"
      }
    ]
  1. 获取特定题目
  • URL: /api/questions/get/{question_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    {
      "question_id": 1,
      "content": "题目内容",
      "question_type": "choice/true_false/fill_in_blank/essay",
      "difficulty_level": "easy/medium/hard",
      "created_at": "创建时间"
    }
  1. 更新题目
  • URL: /api/questions/update/{question_id}/

  • 方法: PUT

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "content": "新题目内容",
      "question_type": "新题目类型",
      "difficulty_level": "新难度级别"
    }
  • 响应:

    json 复制代码
    {
      "question_id": 1,
      "content": "新题目内容",
      "question_type": "新题目类型",
      "difficulty_level": "新难度级别",
      "created_at": "创建时间"
    }
  1. 删除题目
  • URL: /api/questions/delete/{question_id}/
  • 方法: DELETE
  • 请求头: Authorization: Bearer {token}
  • 响应: 204 No Content

3.3 考试管理

  1. 创建考试
  • URL: /api/exams/create/

  • 方法: POST

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "exam_name": "考试名称",
      "start_time": "开始时间",
      "end_time": "结束时间",
      "duration": 120
    }
  • 响应:

    json 复制代码
    {
      "exam_id": 1,
      "exam_name": "考试名称",
      "start_time": "开始时间",
      "end_time": "结束时间",
      "duration": 120,
      "created_at": "创建时间"
    }
  1. 获取所有考试
  • URL: /api/exams/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "exam_id": 1,
        "exam_name": "考试名称",
        "start_time": "开始时间",
        "end_time": "结束时间",
        "duration": 120,
        "created_at": "创建时间"
      }
    ]
  1. 获取特定考试
  • URL: /api/exams/get/{exam_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    {
      "exam_id": 1,
      "exam_name": "考试名称",
      "start_time": "开始时间",
      "end_time": "结束时间",
      "duration": 120,
      "created_at": "创建时间"
    }
  1. 更新考试
  • URL: /api/exams/update/{exam_id}/

  • 方法: PUT

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "exam_name": "新考试名称",
      "start_time": "新开始时间",
      "end_time": "新结束时间",
      "duration": 150
    }
  • 响应:

    json 复制代码
    {
      "exam_id": 1,
      "exam_name": "新考试名称",
      "start_time": "新开始时间",
      "end_time": "新结束时间",
      "duration": 150,
      "created_at": "创建时间"
    }
  1. 删除考试
  • URL: /api/exams/delete/{exam_id}/
  • 方法: DELETE
  • 请求头: Authorization: Bearer {token}
  • 响应: 204 No Content
  1. 添加题目到考试
  • URL: /api/exams/add_question/

  • 方法: POST

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "exam": 1,
      "question": 1
    }
  • 响应:

    json 复制代码
    {
      "exam_question_id": 1,
      "exam": 1,
      "question": 1,
      "question_detail": {
        "question_id": 1,
        "content": "题目内容",
        "question_type": "题目类型",
        "difficulty_level": "难度级别",
        "created_at": "创建时间"
      }
    }
  1. 获取考试的所有题目
  • URL: /api/exams/questions/{exam_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "exam_question_id": 1,
        "exam": 1,
        "question": 1,
        "question_detail": {
          "question_id": 1,
          "content": "题目内容",
          "question_type": "题目类型",
          "difficulty_level": "难度级别",
          "created_at": "创建时间"
        }
      }
    ]
  1. 自动组卷
  • URL: /api/exams/generate_paper/

  • 方法: POST

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "exam_id": 1,
      "easy_count": 5,
      "medium_count": 3,
      "hard_count": 2
    }
  • 响应:

    json 复制代码
    {
      "message": "成功添加 10 道题目到考试"
    }

3.4 成绩管理

  1. 添加成绩
  • URL: /api/scores/add/

  • 方法: POST

  • 请求头: Authorization: Bearer {token}

  • 请求体:

    json 复制代码
    {
      "user": 1,
      "exam": 1,
      "score": 85
    }
  • 响应:

    json 复制代码
    {
      "score_id": 1,
      "user": 1,
      "exam": 1,
      "score": 85,
      "created_at": "创建时间",
      "user_detail": {
        "user_id": 1,
        "username": "用户名",
        "role": "角色",
        "created_at": "创建时间"
      },
      "exam_detail": {
        "exam_id": 1,
        "exam_name": "考试名称",
        "start_time": "开始时间",
        "end_time": "结束时间",
        "duration": 120,
        "created_at": "创建时间"
      }
    }
  1. 获取用户成绩
  • URL: /api/scores/user/{user_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "score_id": 1,
        "user": 1,
        "exam": 1,
        "score": 85,
        "created_at": "创建时间",
        "user_detail": {
          "user_id": 1,
          "username": "用户名",
          "role": "角色",
          "created_at": "创建时间"
        },
        "exam_detail": {
          "exam_id": 1,
          "exam_name": "考试名称",
          "start_time": "开始时间",
          "end_time": "结束时间",
          "duration": 120,
          "created_at": "创建时间"
        }
      }
    ]
  1. 获取考试成绩
  • URL: /api/scores/exam/{exam_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "score_id": 1,
        "user": 1,
        "exam": 1,
        "score": 85,
        "created_at": "创建时间",
        "user_detail": {
          "user_id": 1,
          "username": "用户名",
          "role": "角色",
          "created_at": "创建时间"
        },
        "exam_detail": {
          "exam_id": 1,
          "exam_name": "考试名称",
          "start_time": "开始时间",
          "end_time": "结束时间",
          "duration": 120,
          "created_at": "创建时间"
        }
      }
    ]
  1. 获取历史考试记录
  • URL: /api/scores/history/{user_id}/

  • 方法: GET

  • 请求头: Authorization: Bearer {token}

  • 响应:

    json 复制代码
    [
      {
        "history_id": 1,
        "user": 1,
        "exam": 1,
        "score": 85,
        "completed_at": "完成时间",
        "user_detail": {
          "user_id": 1,
          "username": "用户名",
          "role": "角色",
          "created_at": "创建时间"
        },
        "exam_detail": {
          "exam_id": 1,
          "exam_name": "考试名称",
          "start_time": "开始时间",
          "end_time": "结束时间",
          "duration": 120,
          "created_at": "创建时间"
        }
      }
    ]

🦁 其它优质专栏推荐 🦁

🌟《Java核心系列(修炼内功,无上心法)》: 主要是JDK源码的核心讲解,几乎每篇文章都过万字,让你详细掌握每一个知识点!
🌟 《springBoot 源码剥析核心系列》一些场景的Springboot源码剥析以及常用Springboot相关知识点解读

欢迎加入狮子的社区 :『Lion-编程进阶之路』,日常收录优质好文

更多文章可持续关注上方🦁的博客,2025咱们顶峰相见!

相关推荐
爱coding的橙子2 小时前
每日算法刷题Day84:11.11:leetcode 动态规划9道题,用时2h
算法·leetcode·动态规划
shenghaide_jiahu2 小时前
字符串匹配和回文串类题目
学习·算法·动态规划
云动雨颤2 小时前
爬虫是怎么工作的?从原理到用途
爬虫·python·数据挖掘
月下倩影时3 小时前
ROS1基础入门:从零搭建机器人通信系统(Python/C++)
c++·python·机器人
Danceful_YJ3 小时前
36.优化方法
人工智能·pytorch·python·深度学习·优化器算法
C116113 小时前
Jupyter中选择不同的python 虚拟环境
开发语言·人工智能·python
天下不喵3 小时前
Ubuntu24.02安装python库以及部署python项目
python
残雪飞扬3 小时前
Pycharm社区版安装
ide·python·pycharm
有意义3 小时前
为什么说数组是 JavaScript 开发者必须精通的数据结构?
前端·数据结构·算法