Django DRF多测试问答功能的项目架构与实现方案咨询
Django DRF多测试问答功能的项目架构与实现方案咨询
嘿,我之前在Django和DRF里做过好几个类似的在线测试/问答系统,给你梳理下最实用的方案,帮你避开坑:
一、推荐的项目架构设计
首先,别用tests当app名——Django默认就有个tests目录用来写单元测试,重名会搞出一堆麻烦,建议叫assessments或者quizzes更稳妥。
1. 核心模型设计(数据库层面)
用关联模型来组织数据,这是最灵活可扩展的方式:
- Test模型:存测试的基础信息,比如
title(测试标题)、description(测试说明)、time_limit(时长限制,可选)、created_at(创建时间) - Question模型:外键关联到Test,字段包括
test(关联的测试)、content(问题内容)、question_type(题型,比如choice/multiple_choice/text)、points(分值) - Answer模型:外键关联到Question,字段包括
question(关联的问题)、content(选项内容)、is_correct(是否为正确答案,仅客观题用)、order(选项排序,保证客观题选项顺序正确) - (可选)UserTestAttempt模型:如果需要记录用户的答题记录,加这个模型,关联User和Test,存
score(得分)、completed_at(完成时间)、status(是否完成)
2. DRF层实现
- 序列化器:用嵌套序列化器来简化API响应,比如
TestSerializer里嵌套QuestionSerializer,QuestionSerializer里嵌套AnswerSerializer,这样前端请求一个测试详情时,能一次性拿到所有问题和对应选项,不用多次请求。 - 视图集:用
ModelViewSet或者ReadOnlyModelViewSet,搭配权限类控制访问——比如管理员能创建/修改测试,普通用户只能查看测试、提交答题结果。 - 路由:用DRF的
DefaultRouter注册视图集,自动生成RESTful的API端点,比如/api/assessments/tests/、/api/assessments/tests/1/questions/这类。
二、CSV vs 数据库:绝对别直接用CSV存数据!
直接把问答内容存在CSV里真的会给自己挖大坑,原因如下:
- 维护超麻烦:改个问题得打开CSV手动编辑,很容易写错格式,而且没法做权限控制(比如只有特定人能改测试内容)
- 性能拉胯:测试多了之后,读取CSV要全量加载,数据库可以加索引快速查询特定测试的问题
- 无法处理复杂逻辑:比如要统计某个知识点的所有问题、或者用户的答题正确率,CSV根本没法搞
不过CSV可以用来做初始数据导入——比如你已经有一堆现成的问答存在CSV里,写个Django管理命令批量导入到数据库就行,举个简单的示例代码:
# assessments/management/commands/import_tests.py import csv from django.core.management.base import BaseCommand from assessments.models import Test, Question, Answer class Command(BaseCommand): help = '批量从CSV导入测试、问题和答案' def add_arguments(self, parser): parser.add_argument('questions_csv', type=str, help='存储问题的CSV文件路径') parser.add_argument('answers_csv', type=str, help='存储答案的CSV文件路径') def handle(self, *args, **options): # 先导入问题 with open(options['questions_csv'], 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: test, _ = Test.objects.get_or_create(title=row['test_title']) Question.objects.create( test=test, content=row['question_content'], question_type=row['question_type'], points=int(row['points']) ) # 再导入对应答案 with open(options['answers_csv'], 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: question = Question.objects.get(content=row['question_content']) Answer.objects.create( question=question, content=row['answer_content'], is_correct=row['is_correct'] == 'True', order=int(row['order']) ) self.stdout.write(self.style.SUCCESS('数据导入完成!'))
用的时候直接在终端跑python manage.py import_tests questions.csv answers.csv就行。
三、类似项目的实现思路参考
不用找具体的开源项目链接,核心思路都是大同小异的:
- 很多开源的Django在线测试项目,都是用Test-Question-Answer的关联模型结构,有些会把题型做更细的拆分(比如单独的主观题模型),但中小项目用字段标记题型就足够了
- 如果你需要更复杂的逻辑,比如测试的权限控制、用户答题的实时统计,可以参考DRF官方文档里的嵌套序列化器、视图集、权限类的示例,这些基础组件组合起来就能实现大部分需求
四、一些最佳实践
- 用嵌套序列化器减少前端请求次数,比如获取测试详情时,一次性返回所有问题和选项
- 给模型加索引,比如Test的title、Question的test字段,优化查询性能
- 用权限类严格控制API访问:比如管理员能CRUD测试,普通用户只能GET测试、POST答题结果
- 写单元测试:针对模型、序列化器、视图集写测试用例,保证修改代码时不破坏现有功能
备注:内容来源于stack exchange,提问作者Qazaaleh Taheri
相关产品推荐
相关产品推荐

