You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:09:51