Django在线考试系统源码解析:从环境搭建到自动判分
简介这是一套基于Python与Django框架开发的在线考试系统完整项目面向计算机相关专业的毕业设计、课程作业以及需要快速搭建考试平台的开发者。系统采用管理员、教师、学生三角色分级权限设计覆盖用户注册登录、班级课程关联、题库维护、智能组卷、考试发布与成绩统计等核心流程支持单选、多选、判断、填空、简答及可在线运行的Python编程题并提供Excel/Word批量导入与多条件检索能力。资源包共607个文件约21.63MB以Vue组件、JavaScript脚本、Python后端代码、SVG图标与图片素材为主另含SQL建库脚本、配置文件及数据库文档前端界面与后端逻辑分层清晰便于二次开发与部署调试。目前已有66人学习下载适合作为毕业设计参考或课程实践模板帮助读者快速理解在线考试系统的整体架构与业务实现。1. 从一份 Django 在线考试系统源码说起它到底能跑通什么如果你正在做毕业设计或者课程作业大概率会遇到这个场景题目定了「基于 Python 的在线考试系统」技术栈选了 Django但真正动手时发现——题库怎么建模、考试倒计时怎么控制、交卷后客观题怎么自动判分、数据库文档到底要写到什么颗粒度每一步都是坑。这份资源就是一套已经跑通的 Django 在线考试系统源码附带数据库设计文档覆盖了从用户角色、题库管理、组卷策略到考试记录、成绩统计的完整链路。它适合三类人一是毕设选题卡在「有功能但不成体系」的同学需要一份结构完整的参考实现二是刚学完 Django 基础、想找一个真实项目练手的入门者三是需要快速搭出考试模块原型的开发者。核心价值不在于代码多高级而在于它把「考试」这个业务场景里的关键约束——限时、防重复提交、客观题自动判分、主观题人工批阅——都用 Django 的常规能力落地了没有引入过重的中间件本地跑起来门槛低。2. 环境搭建与项目启动从 Python 安装到 runserver 跑通2.1 依赖版本与虚拟环境选择拿到源码包后第一件事不是急着pip install而是先确认 Python 版本和 Django 版本的匹配关系。这套项目基于 Django 3.x 或 4.x 的常规写法如果你本地装的是 Python 3.12 而 Django 锁在 3.2部分依赖会编译失败。常见做法是建一个独立虚拟环境把版本钉死。# 创建虚拟环境python3 -m venv 是标准做法 python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate # 安装依赖建议先看 requirements.txt 里 Django 的版本号 pip install -r requirements.txt这里的关键参数是requirements.txt里的 Django 版本。如果文件里写的是Django3.2.18就不要手动升级到 4.x因为 4.x 里url()被re_path()替代、django.conf.urls的导入方式也有变化直接跑会报ImportError。虚拟环境的作用是把项目依赖和系统 Python 隔开避免你之前装的爬虫库、数据分析库干扰 Django 的版本解析。2.2 数据库配置与迁移项目默认可能用 SQLite也可能用 MySQL。数据库文档里一般会给出表结构但代码里的settings.py才是真正生效的地方。打开settings.py找到DATABASES配置段# settings.py 数据库配置示例 DATABASES { default: { ENGINE: django.db.backends.mysql, # 如果用 MySQL NAME: exam_system, # 数据库名需提前建好 USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, # 支持中文和 emoji } } }参数说明NAME对应的数据库必须先在 MySQL 里CREATE DATABASE exam_system DEFAULT CHARSETutf8mb4;建好Django 不会自动建库。utf8mb4而不是utf8是因为考试系统里题干可能包含特殊符号utf8在三字节以上字符会截断。配好后执行迁移python manage.py makemigrations python manage.py migrate python manage.py createsuperuser # 创建后台管理员 python manage.py runservermakemigrations是根据models.py生成迁移文件migrate才是真正在数据库里建表。如果这一步报django.db.utils.OperationalError九成是数据库没建、密码错、或者 MySQL 服务没启动。createsuperuser创建的账号用来登录 Django admin 后台题库录入、用户管理都在那里操作。2.3 静态文件与模板路径排查启动后如果页面样式全丢、图片裂开通常是静态文件路径没配对。Django 在DEBUGTrue时由django.contrib.staticfiles自动服务静态文件但前提是INSTALLED_APPS里有这个 app且模板里用{% static %}标签而不是硬编码/static/xxx。!-- 模板中正确引用静态文件的方式 -- {% load static %} link relstylesheet href{% static css/exam.css %}如果你在 VS Code 里写img src/static/img/logo.png发现显示不了先检查settings.py里STATIC_URL是不是/static/再确认图片实际放在app/static/img/目录下。Django 的静态文件查找是按 app 逐个扫描static子目录不是项目根目录下的static除非你额外配了STATICFILES_DIRS。这个点新手翻车率极高血泪经验是路径没错但 404八成是目录层级放错了。3. 核心数据模型拆解题库、试卷、考试记录怎么建3.1 题库模型与题型字段设计在线考试系统的地基是题库模型。这套源码里通常会把题目和选项拆成两张表或者用 JSON 字段存选项。拆表的好处是查询灵活、便于统计每个选项的选择分布JSON 字段的好处是结构简单、一次查询拿全。数据库文档里一般会标注字段类型和约束下面是一个典型的题目模型# models.py 题目模型 class Question(models.Model): QUESTION_TYPE ( (single, 单选题), (multiple, 多选题), (judge, 判断题), (essay, 简答题), ) content models.TextField(verbose_name题干) q_type models.CharField(max_length10, choicesQUESTION_TYPE) score models.IntegerField(default5, verbose_name分值) answer models.TextField(verbose_name正确答案) analysis models.TextField(blankTrue, verbose_name解析) category models.ForeignKey(Category, on_deletemodels.SET_NULL, nullTrue)参数说明q_type用choices约束取值范围避免脏数据score默认 5 分组卷时按总分动态调整answer对于多选题存成A,B,C这种逗号分隔字符串判分时拆分比对category外键指向分类表on_deleteSET_NULL表示分类删除后题目保留但分类置空比级联删除安全。数据库文档里会把这些字段的注释、索引、默认值列成表格写毕设时直接引用即可。3.2 试卷与考试记录模型试卷模型的核心是「组卷策略」——是固定题目还是随机抽题。固定试卷把题目 ID 存成关联表随机试卷则在创建考试记录时按分类和数量抽题快照。考试记录模型要记录考生、试卷、开始时间、交卷时间、得分、状态。# 考试记录模型 class ExamRecord(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) paper models.ForeignKey(Paper, on_deletemodels.CASCADE) start_time models.DateTimeField(auto_now_addTrue) submit_time models.DateTimeField(nullTrue, blankTrue) score models.IntegerField(default0) status models.CharField(max_length10, defaultongoing) # ongoing/finishedauto_now_addTrue让开始时间在记录创建时自动写入不需要前端传。submit_time允许为空因为考试进行中还没有交卷。status字段用来控制「同一份试卷不能重复交卷」——交卷时先查status是否为ongoing是才允许更新否则返回「已交卷」。这个逻辑在视图里用select_for_update()加行锁更稳妥防止并发交卷导致分数覆盖。3.3 数据库文档的颗粒度要求数据库文档不是把models.py翻译一遍就完事。合格的文档至少包含表名、字段名、字段类型、是否为空、默认值、注释、索引、外键关系。毕设答辩时老师常问「这个字段为什么这么设计」文档里最好附一句设计理由。比如answer字段用 TextField 而不是 CharField是因为简答题答案可能很长score用 IntegerField 而不是 FloatField是因为考试分数一般取整避免浮点误差。字段名类型允许空默认值说明contenttext否无题干内容q_typevarchar(10)否无题型枚举scoreint否5题目分值answertext否无标准答案analysistext是空答案解析这张表可以直接放进论文的「数据库设计」章节比截图 ER 图更清晰。4. 考试流程实现组卷、倒计时、交卷判分的代码落地4.1 随机组卷与题目快照随机组卷的常见做法是考生点击「开始考试」时后端按试卷配置的分类和数量从题库里order_by(?)随机抽取然后把抽到的题目 ID 写入考试记录关联表。这样每份试卷的题目顺序和内容都是独立的避免相邻考生互相偷看。# 组卷逻辑 import random from .models import Question, ExamRecord, RecordQuestion def generate_paper(paper, user): record ExamRecord.objects.create(useruser, paperpaper) for rule in paper.rules.all(): # rules 存分类和抽题数量 questions list(Question.objects.filter( categoryrule.category, q_typerule.q_type )) selected random.sample(questions, min(rule.count, len(questions))) for q in selected: RecordQuestion.objects.create(recordrecord, questionq) return recordrandom.sample而不是order_by(?)是因为后者在数据量大时会对全表排序性能差。min(rule.count, len(questions))防止题库题目不够时sample报错。抽题后写入RecordQuestion关联表相当于给这次考试做了一份题目快照——即使后续题库修改已生成的试卷不受影响。这个设计在数据库文档里体现为一张中间表字段包括record_id和question_id。4.2 倒计时与自动交卷倒计时有两种实现前端 JS 计时、后端记录截止时间。只做前端计时的话考生刷新页面或改系统时间就能重置所以必须后端兜底。常见做法是在ExamRecord里加一个deadline字段开始考试时写入start_time paper.duration。# 后端校验是否超时 from django.utils import timezone def check_timeout(record): if timezone.now() record.deadline: if record.status ongoing: auto_submit(record) # 自动交卷只判已答题目 return True return False前端用 JS 每秒刷新剩余时间到 0 时自动提交表单。但后端在每次保存答案和交卷时都要调check_timeout防止前端计时被绕过。timezone.now()而不是datetime.now()是因为 Django 开启了时区支持后数据库存的是 UTC 时间直接用datetime.now()会差 8 小时这个坑非常隐蔽。4.3 客观题自动判分与主观题标记交卷时遍历该考试记录的所有题目客观题比对答案主观题标记为待批阅。判分逻辑要处理多选题的「少选得分」还是「少选不得分」这套源码一般按「完全匹配才得分」处理简单可靠。# 自动判分 def auto_grade(record): total 0 for rq in record.recordquestion_set.all(): q rq.question if q.q_type in (single, judge): if rq.user_answer q.answer: total q.score elif q.q_type multiple: user_set set(rq.user_answer.split(,)) correct_set set(q.answer.split(,)) if user_set correct_set: total q.score else: rq.need_manual True # 主观题标记人工批阅 rq.save() record.score total record.status finished record.submit_time timezone.now() record.save()set比对多选题答案避免顺序不同导致误判。主观题不自动给分而是打上need_manual标记后台管理员在 admin 里逐条批阅。这里要注意user_answer如果为空字符串split(,)会得到[]和正确答案比对不相等所以未作答的题目自然得 0 分不需要额外判断。5. 避坑与排查那些跑起来才会暴露的问题5.1 迁移报错 No changes detected现象执行makemigrations提示No changes detected但明明改了models.py。原因通常是 app 没有加入INSTALLED_APPS或者models.py里的类没有继承models.Model。解决检查settings.py的INSTALLED_APPS是否包含该 app 名称再确认模型类定义正确。如果 app 是后来创建的还要确保apps.py里的name和实际路径一致。5.2 静态文件 404 但路径看着没错现象浏览器控制台报GET /static/css/exam.css 404但文件确实存在。原因多半是DEBUGFalse时 Django 不再自动服务静态文件或者STATICFILES_DIRS没配。解决开发阶段保持DEBUGTrue如果必须DEBUGFalse用python manage.py collectstatic把静态文件收集到STATIC_ROOT再由 Nginx 或 WhiteNoise 托管。VS Code 里写 img 标签显示不了先确认{% load static %}有没有加。5.3 交卷后分数为 0 或答案丢失现象考生答完题交卷成绩是 0或者部分答案没保存。原因可能是前端表单字段名和后端request.POST.get()的 key 不一致或者保存答案时没有关联到正确的RecordQuestion。解决在视图里打印request.POST看实际提交的键名确认每道题的 input name 带上了题目 ID比如nameq_12后端按q_前缀解析。另一个常见原因是 CSRF token 没带POST 被 403 拦截答案根本没到后端。5.4 时区导致倒计时差 8 小时现象后端记录的deadline和前端显示剩余时间对不上或者自动交卷提前/延后触发。原因settings.py里USE_TZTrue时数据库存 UTC而datetime.now()返回本地时间。解决统一用django.utils.timezone.now()模板里用{{ deadline|date:Y-m-d H:i:s }}会自动转成TIME_ZONE设置的时区。如果不想折腾时区把USE_TZFalse也能跑但数据库文档里要注明这个取舍。5.5 并发交卷导致分数覆盖现象同一考生开两个标签页同时交卷最终分数是其中一次的另一次答案丢失。原因两个请求同时读到statusongoing都执行了判分和更新。解决交卷视图里用ExamRecord.objects.select_for_update().get(idrecord_id)加行锁或者在更新时用filter(statusongoing).update(...)判断受影响行数为 0 则说明已被其他请求处理。这个点在小规模考试里不明显但数据库文档里最好把status字段的并发控制写进设计说明。6. 二次开发与验证把这份源码改成你自己的毕设拿到源码后直接交差只能算及格真正让答辩老师眼前一亮的是你能说清楚「我改了什么、为什么改」。一个具体技巧是先跑通原始流程然后用 Django 的shell逐条验证数据流转。python manage.py shell# 在 shell 里验证组卷和判分 from exam.models import * from exam.views import generate_paper, auto_grade user User.objects.first() paper Paper.objects.first() record generate_paper(paper, user) print(record.recordquestion_set.count()) # 确认抽题数量 # 模拟作答 for rq in record.recordquestion_set.all(): rq.user_answer rq.question.answer # 全部答对 rq.save() auto_grade(record) print(record.score) # 应该等于试卷总分这段脚本能在不启动前端的情况下验证核心逻辑比点页面快得多。如果record.score不等于预期总分就逐题打印rq.question.q_type和rq.user_answer定位是哪类题型判分出了问题。二次开发的方向通常有三个一是加 WebSocket 实现后台有数据时前端实时推送比如管理员发布新考试考生页面自动提示Django Channels 是常见方案二是加 RBAC 权限控制把「出题人」「阅卷人」「考生」角色分开Django 自带的Group和Permission够用三是把数据库文档补全成论文格式加上 ER 图和字段设计理由。我自己的习惯是每次改完models.py先makemigrations看迁移文件内容确认没有误删字段再migrate。从那以后我每次动数据库结构都强制走一遍「备份 → 迁移 → 验证」三步再也没出现过数据丢失。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

GRBL速度前瞻算法解析:反向规划与正向规划让雕刻机告别顿挫

GRBL速度前瞻算法解析:反向规划与正向规划让雕刻机告别顿挫

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:39:10 阅读更多 →
激光分束与偏折:从物理原理到工程应用的全解析

激光分束与偏折:从物理原理到工程应用的全解析

开头不想说废话,直接讲关键点:激光的分束与偏折,本质上是同一件事的两面——分束是把一束光的能量在空间上重新分配,偏折是让光束的传播方向发生变化。但搞激光应用的人都知道,这两件事在实际工程里远比教科书上的折射…

2026/9/25 6:39:10 阅读更多 →
【大道至简(一)】Cursor 代码审查与管理备份:用 TaoToken 统一 Key 打通配置骨架

【大道至简(一)】Cursor 代码审查与管理备份:用 TaoToken 统一 Key 打通配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:39:09 阅读更多 →

最新新闻

金融场景下Claude协作体系:权限、脱敏与审计的工程实践

金融场景下Claude协作体系:权限、脱敏与审计的工程实践

1. 金融场景下 Claude 协作体系的设计思路1.1 为什么金融行业需要一套独立的协作规范金融行业对 AI 辅助工具的诉求和普通互联网团队完全不一样。普通团队用 Claude 写写代码、改改文案,出错了顶多重来一次;但金融场景里,一段错误的合规话术、…

2026/9/25 7:17:42 阅读更多 →
microduck vision-demo 技术解析:让家用路由器后面的机器人把相机帧直接推给数据中心 Space

microduck vision-demo 技术解析:让家用路由器后面的机器人把相机帧直接推给数据中心 Space

机器人嵌入式强化学习人工智能智能硬件计算机视觉音视频 【免费下载链接】microduck A Tiny biped duck robot 🦆 项目地址: https://gitcode.com/gh_mirrors/mi/microduck 点击查看 免费下载 microduck 是一个微型双足机器人项目,其 spaces…

2026/9/25 7:17:42 阅读更多 →
Atlas 300V NPU推理卡部署YOLOv8实战:从ONNX到OM全流程指南

Atlas 300V NPU推理卡部署YOLOv8实战:从ONNX到OM全流程指南

后台一直有人问我:Atlas 300V 24G是不是运算加速卡?能不能用它部署YOLO?这两个问题,我在一个工业质检项目里实际都验证过了。先说结论:Atlas 300V是一款面向推理场景的AI加速卡,也就是我们常说的“NPU推理卡…

2026/9/25 7:17:42 阅读更多 →
影视APP双端源码落地指南:结构识别、排错与播放器对接

影视APP双端源码落地指南:结构识别、排错与播放器对接

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 7:17:42 阅读更多 →
BLDC六步换相实战:霍尔信号采集、换相查表与PWM驱动

BLDC六步换相实战:霍尔信号采集、换相查表与PWM驱动

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 7:17:42 阅读更多 →
The Concise TypeScript Book 精讲:TypeScript 三斜线指令(Triple-Slash Directives)完整指南

The Concise TypeScript Book 精讲:TypeScript 三斜线指令(Triple-Slash Directives)完整指南

文档教程 【免费下载链接】typescript-book The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source. 项目地址: https://gitcode.com/gh_mirrors/typ/typescript-book 点击查看 免费下载 三斜线指令&#x…

2026/9/25 7:16:42 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →