问卷设计的问题

之前的一个网站项目中,对方希望我们实现一个允许用户自定义的问卷系统。我之前也没有什么经验,经过摸索做出了如下的设计,这里和大家分享一下。按照要求,问卷中包含四种不同的问题:单选题

多选题

问答题

图片题

问卷中问题的种类和数量不限。

设计思路

问卷系统首先可以拆解成为两个部分,一是问卷结构的设计,二是答卷结构的设计。二者十分类似,但是又略有不同。

问卷结构设计

一副问卷应当有一个统一的入口,一个对应于『问卷』这一实体概念的抽象。问卷拥有一些描述整体的属性,如创建时间,创建问卷的等等(有的人可能会试图将回答了问卷的用户和这里的问卷本身联系起来,但事实上和这些用户关联的应当是答案)。同时,不同的问题隶属于一个共同的问卷实体。这些问题,既共享一些通用的性质,但是基于不同的具体问题类型而又有不同的特点(选择题和问答题就有不同的属性)。特别的,对于选择题而言,题目和选项又建立起了一对多的关系。综合上面的描述,问卷部分的结构应当如下图所示:

Struction of questionnaire

答卷结构设计

显然,问卷和答卷直接是应该是一对多的。而答卷又是由针对问卷中各个问题的答案组成的。特别的,选择题的答案又指向所选的选项。故而,答卷部分的结构和问卷部分基本是相同的。

示例代码

以开头我说的问题为例。

问卷

首先我们需要为问卷建立一个modelclass Questionnaire(models.Model):

created_at = models.DateTimeField(auto_now_add=True, editable=False)

modified_at = models.DateTimeField(auto_now=True, editable=False)

is_active = models.BooleanField(default=True)

participants = models.ManyToManyField(settings.AUTH_USER_MODEL)

user = models.ForeignKey(settings.AUTH_USER_MODEL)    def __str__(self):

return smart_str(self.user.username + "的问卷")    class Meta:

ordering = ["-created_at"]

由于不同的问题具有一些共享的属性,我们可以创建一个抽象的基类类表示这些共通的属性,例子如下:class Question(models.Model):

"""这个类是单个问题的抽象"""

question = models.CharField(max_length=200, verbose_name="问题")

required = models.BooleanField(default=True, help_text="这个问题是否必须回答")

questionnaire = models.ForeignKey(Questionnaire)

order_in_list = models.IntegerField(default=1)  # 在问卷列表中的顺序,从1开始

created_at = models.DateTimeField(auto_now_add=True, editable=False)

class Meta:

abstract = True

为不同问题类型我们需要创建对应的model:class ChoiceQuestion(Question):

"""选择题"""

multi_choice = models.BooleanField(default=False, verbose_name="是否为多选")

TEXT_QUESTION_TYPE = 0FILE_QUESTION_TYPE = 1class NonChoiceQuestion(Question):

"""主观题"""

type = models.SmallIntegerField(verbose_name="主观题类型",

choices=(

(TEXT_QUESTION_TYPE, '问答题'),

(FILE_QUESTION_TYPE, '文件题')

), default=0)

虽然问题描述中给出了4中不同的问题,但是实际上只需要两类就足以描述。中单选题和多选题只是能够同时选择的选项数量不同,题目本身的描述特点是相同的。而文件题和问答题只是答案的形式不一样,题目本身的描述特点是一样的。(综上来看,问题主要是表现问题的『描述』性)

最后,我们需要为问答题设计选项:class Choice(models.Model):

question = models.ForeignKey(ChoiceQuestion, related_name="choices")

description = models.CharField(max_length=50)

multi_choice = models.BooleanField(default=False, verbose_name="是否为多选")

order_in_list = models.IntegerField(default=1)  # 在选项列表中的顺序,从1开始

答案部分

首先是答卷:class AnswerSheet(models.Model):

"""答卷的抽象"""

user = models.ForeignKey(settings.AUTH_USER_MODEL)      # 答题者

questionnaire = models.ForeignKey(Questionnaire)     # 对应问卷

created_at = models.DateTimeField(auto_now_add=True, editable=False)

modified_at = models.DateTimeField(auto_now=True, editable=False)

is_active = models.BooleanField(default=True)

答案则无法像问题只需要两个类既可以表示,这里我们需要为四种问题设计四种答案类:class Answer(models.Model):

"""答案的基类"""

answer_sheet = models.ForeignKey(AnswerSheet)    class Meta:

abstract = Trueclass SingleChoiceAnswer(Answer):

"""单选题的答案"""

choice = models.ForeignKey(Choice, related_name="single_choice_answers")  # 单选题

question = models.ForeignKey(ChoiceQuestion, related_name="single_choice_answer_set")class MultiChoiceAnswer(Answer):

"""多选题的答案"""

choices = models.ManyToManyField(Choice, related_name="multi_choice_answers")

question = models.ForeignKey(ChoiceQuestion, related_name="multi_choice_answers")class TextAnswer(Answer):

"""文字题的答案"""

text = models.TextField()

question = models.ForeignKey(NonChoiceQuestion)class FileAnswer(Answer):

file = models.ImageField(upload_to="your_upload_path")

question = models.ForeignKey(NonChoiceQuestion)

is_image = models.BooleanField(default=True)

综上我们就完成了这个可定制答卷的model部分。

作者:治部少辅

链接:https://www.jianshu.com/p/a558d5b52348

打开App,阅读手记

django问卷html,Django:动态问卷系统的Model设计相关推荐

  1. SMARTS 动态问卷

    SMARTS 动态问卷 SMARTS决策管理平台包含一个强大的功能模块----动态问卷.使用动态问卷,应用程序能与用户在自定义的上下文环境中进行动态交互,针对性收集相关信息. 动态问卷适用场景 在信贷 ...

  2. svc的参考文献_无功补偿论文,关于svc动态无功补偿系统的设计相关参考文献资料-免费论文范文...

    导读:本文关于无功补偿论文范文,可以做为相关论文参考文献,与写作提纲思路参考. (1.国核电力规划设计研究院,中国 北京 100095:2.山东科技大学,山东 青岛 266590: 无功补偿原理:无功 ...

  3. [附源码]Python计算机毕业设计调查问卷及调查数据统计系统Django(程序+LW)

    该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程 项目运行 环境配置: Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+N ...

  4. [附源码]Python计算机毕业设计调查问卷及调查数据统计系统

    项目运行 环境配置: Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+Navicat11+Django+nodejs. 项目技术: dj ...

  5. Python-Django毕业设计调查问卷及调查数据统计系统(程序+Lw)

    该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程 项目运行 环境配置: Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+N ...

  6. 计算机毕业设计python+django股票基金模拟交易系统(源码+系统+mysql数据库+Lw文档)

    项目介绍 股票信息管理系统,又称为网站股票信息发布系统,是将网页上的某些需要经常变动的信息,类似各类股票信息.最新产品信息发布和业界动态等更新信息集中管理,并通过信息的某些共性进行分类,最后系统化.标 ...

  7. python路由编程_Python Django基础二之URL路由系统

    MVC和MTV框架 MVC Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一起,模型负责业务 ...

  8. Django 模板实现(动态)图片/头像展示到页面

    Django 模板实现(动态)图片作头像展示到页面 在网上搜了加载图片到前端的解决方法,大多都比较复杂,要引用PIL,下载Cropper插件(可以用于裁图)之类的,下面是一个简单易懂的方法实现(动态) ...

  9. Django自定义User模型以及用户系统(用户、权限、组)的使用

    Django自带强大的User系统,为我们提供用户认证.权限.组等一系列功能,可以快速建立一个完整的后台功能. 但User模型并不能满足我们的需求,例如自带的User表中没有手机号码,而且对于国人来说 ...

最新文章

  1. 单片机值得学吗?会单片机能找什么工作?
  2. python中如何在写文件之前删除文件内容_Python:文件的读取、创建、追加、删除、清空...
  3. SAP从视图获得数据
  4. C++ 中关于optional 使用过程中遇到的问题
  5. python函数的作用域_python学习第五篇 函数 变量作用域
  6. github之关联远程仓库
  7. static和const关键字
  8. selenium chromedriver usage
  9. 推荐几个好用的插件(Edge)
  10. 保姆级详细介绍Navicat安装会出现的四种问题,详细给出解决办法
  11. 八数码 (Astar)
  12. 日期转换 EEE MMM dd HH:mm:ss zzz yyyy
  13. 【Task02】Pandas之基础
  14. 《疯狂java讲义》学习(44):线程同步
  15. 三菱modbusRTU通讯实例_三菱PLC的无线通讯实例
  16. Excel如何快速填写二维表
  17. L1-040. 最佳情侣身高差(有坑点)
  18. 两位“世界杰出女科学家成就奖” 获奖女科学家荣获诺贝尔化学奖
  19. 中间件是什么?Linux常用中间件都有哪些?
  20. 灵魂发问!Java并发和线程池,只言片语真的可以讲清楚吗?

热门文章

  1. anemometer mysql 500_Anemometer将Mysql慢查询日志可视化
  2. python count函数代码_python中count函数简单用法
  3. spark count统计元素个数
  4. PDF处理软件:无法加注释加高亮(解密PDF等)
  5. 路由器以太网口静态链路聚合
  6. PHP电商的sku,PHP 商品SKU表怎么设计
  7. item_get - 根据ID获取拼多多商品详情
  8. 收银系统可以管理童装店衣服不同的尺码吗?
  9. 如何查看网页上的图片体积大小或容量大小?
  10. linux常用免杀,【kali linux】详细分析两个免杀远控 了解远控和免杀原理