失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 调查问卷表结构设计及具体实现

调查问卷表结构设计及具体实现

时间:2023-12-26 12:36:08

相关推荐

调查问卷表结构设计及具体实现

一、表结构设计

from django.db import models# Create your models here.class UserInfo(models.Model):'''员工表'''username = models.CharField(max_length=64,verbose_name="用户名")password = models.CharField(max_length=32,verbose_name="用户密码")def __str__(self):return self.usernameclass Meta:verbose_name_plural="员工表"class ClassList(models.Model):'''班级表'''title = models.CharField(max_length=32,verbose_name="班级名")def __str__(self):return self.titleclass Meta:verbose_name_plural = "班级表"class Student(models.Model):'''学生表'''name = models.CharField(max_length=32,verbose_name="学生姓名")password = models.CharField(max_length=32,verbose_name="学生密码")cls = models.ForeignKey(to="ClassList",verbose_name="所属班级")def __str__(self):return self.nameclass Meta:verbose_name_plural = "学生表"class Questionnaire(models.Model):'''问卷表'''title = models.CharField(max_length=32,verbose_name="问卷名")cls = models.ForeignKey(to="ClassList",verbose_name="问卷班级")create_user = models.ForeignKey(to="UserInfo",verbose_name="创建问卷的用户")def __str__(self):return self.titleclass Meta:verbose_name_plural = "问卷表"class Questions(models.Model):'''问卷问题表'''caption = models.CharField(max_length=32,verbose_name="问题题目")type_choices = ((1,"打分"),(2,"单选"),(3,"评价"))question_type = models.IntegerField(choices=type_choices,verbose_name="问题类型")questionnaire = models.ForeignKey(to="Questionnaire",verbose_name="所属问卷",default=1)def __str__(self):return self.captionclass Meta:verbose_name_plural = "问卷问题表"class Answer(models.Model):'''问卷回答表''' #谁什么时候对那个问题作答了student = models.ForeignKey(to="Student",verbose_name="所属学生")queston = models.ForeignKey(to="Questions",verbose_name="所属问题")option = models.ForeignKey(to="Option",null=True,blank=True)val = models.IntegerField(null=True,blank=True,verbose_name="数字答案")content = models.CharField(max_length=255,null=True,blank=True,verbose_name="文本答案")def __str__(self):return self.contentclass Meta:verbose_name_plural = "问卷回答表"class Option(models.Model):'''问卷单选题的选项表'''name = models.CharField(max_length=32,verbose_name="选项名")score = models.IntegerField(verbose_name="选项对应的分值")question = models.ForeignKey(to="Questions",verbose_name="所属问题")def __str__(self):return str(self.score)class Meta:verbose_name_plural = "问卷单选题的选项表"

二、具体实现

urls.py

1 from django.conf.urls import url2 from django.contrib import admin3 from app01 import views4 urlpatterns = [5url(r'^admin/', admin.site.urls),6url(r'^index/$', views.index),7url(r'^questionedit/(\d+)/$', views.questionedit),8url(r'^questionedit2/(\d+)/$', views.questionedit2),9url(r'^questionsave/(\d+)/$', views.questionsave),10url(r'^student_login/$', views.student_login),11url(r'^score/(\d+)/(\d+)/$', views.score),12 ]

urls.py

views.py

1 from django.core.validators import RegexValidator2 from django.db.models.aggregates import Count3 from django.forms.forms import Form4 from django.http.response import JsonResponse5 from django.shortcuts import render, HttpResponse,redirect6 from app01 import models7 from django.forms import ModelForm,fields,widgets8 import json9 from django.core.exceptions import ValidationError10 from django.core.validators import RegexValidator11 # Create your views here.12 def index(request):13Questionnaire_obj = models.Questionnaire.objects.all()14#查询问卷所属的班级的学生个数15for naire in Questionnaire_obj:16 naire.part_num = models.Answer.objects.filter(queston__in=naire.questions_set.all()).values_list('student_id').distinct().count()17 print(naire.part_num)18return render(request,"index.html",{"Questionnaire_obj":Questionnaire_obj})19 20 class QuestionForm(ModelForm):21class Meta:22 model = models.Questions23 fields = ["caption","question_type"]24 25 error_messages = {26 "caption":{"required":"不能为空"}27 }28 widgets ={29 "caption":widgets.Textarea(attrs={"class": "question","rows":0,"cols":0})30 }31 32 class OptionModelForm(ModelForm):33class Meta:34 model = models.Option35 fields = ["name","score"]36 37 def questionedit(request,nid):38# 方式一:39# #查询当前问卷的所有的问题40# que_list = models.Questions.objects.filter(questionnaire_id=nid).all()41# question_list = []42# if not que_list:43#'''新建的问题,还没有创建问题'''44#form = QuestionForm()45#question_list.append(form)46#return render(request,"questionedit.html",{"question_list":question_list})47# else:48#'''已经创建了问题的'''49#for que in que_list:50# print(que,"que===")51# form = QuestionForm(instance=que)52# question_list.append(form)53# return render(request,"questionedit.html",{"question_list":question_list})54 55# 方式二:56#查询当前问卷的所有的问题57# def inner():58#que_list = models.Questions.objects.filter(questionnaire_id=nid).all()59#if not que_list:60# '''新建的问题,还没有创建问题'''61# form = QuestionForm()62# yield form63#else:64# '''已经创建了问题的'''65# for que in que_list:66# form = QuestionForm(instance=que)67# yield form68# return render(request,"questionedit.html",{"form":inner()})69 70 71# 方式三,yield返回的时候吧form作为一个字典的key返回72# def inner():73#que_list = models.Questions.objects.filter(questionnaire_id=nid).all()74#if not que_list:75# '''新建的问题,还没有创建问题'''76# form = QuestionForm()77# yield {"form":form,"obj":None}78#else:79# '''已经创建了问题的'''80# for que in que_list:81# print(que)82# form = QuestionForm(instance=que)83# temp = {"form":form,"obj":que,"option_class":"hide","options":None}84# if que.question_type == 2:85# '''如果选项类型是单选的时候'''86# temp["option_class"] = ""87# #如果是单选的时候让显示所有的选项88# question_option_list =[]89# option_list = models.Option.objects.filter(question=que)90# for obj in option_list:91# vm = OptionModelForm(instance=obj)92# question_option_list.append(vm)93# print(question_option_list,"pppppppppppppp")94# temp["options"] = question_option_list95# yield temp96# return render(request, "questionedit.html", {"form": inner()})97 98# 方式四99def inner():100 que_list = models.Questions.objects.filter(questionnaire_id=nid).all()101 if not que_list:102 '''新建的问题,还没有创建问题'''103 form = QuestionForm()104 yield {"form":form,"obj":None,'option_class':"hide","options":None}105 else:106 '''已经创建了问题的'''107 for que in que_list:108 print(que)109 form = QuestionForm(instance=que)110 temp = {"form":form,"obj":que,"option_class":"hide","options":None}111 if que.question_type == 2:112 '''如果选项类型是单选的时候'''113 temp["option_class"] = ""114 #如果是单选的时候让显示所有的选项115 def inner_loop(quee):116option_list = models.Option.objects.filter(question=quee)117for v in option_list:118 yield {"form":OptionModelForm(instance=v),"obj":v}119 temp["options"] = inner_loop(que)120 yield temp121return render(request, "questionedit.html", {"form": inner(),"nid":nid})122 123 def questionedit2(request,nid):124 def inner():125 que_list = models.Questions.objects.filter(questionnaire_id=nid).all()126 if not que_list:127 '''新建的问题,还没有创建问题'''128 form = QuestionForm()129 yield {"form": form, "obj": None, 'option_class': "hide", "options": None}130 else:131 '''已经创建了问题的'''132 for que in que_list:133 print(que)134 form = QuestionForm(instance=que)135 temp = {"form": form, "obj": que, "option_class": "hide", "options": None}136 if que.question_type == 2:137'''如果选项类型是单选的时候'''138temp["option_class"] = ""139 140# 如果是单选的时候让显示所有的选项141def inner_loop(quee):142 option_list = models.Option.objects.filter(question=quee)143 for v in option_list:144 yield {"form": OptionModelForm(instance=v), "obj": v}145 146temp["options"] = inner_loop(que)147 yield temp148 return render(request,"questionedit.html",{"form":inner()})149 150 151 def questionsave(request,nid):152ret = {"status":True,"msg":None,"data":None}153try:154 if request.is_ajax():155 #得到新提交的数据156 data=request.body.decode("utf8")157 post_data_list = json.loads(data)158 #找到所有的问题列表159 question_list = models.Questions.objects.filter(questionnaire_id=nid)160 #找到用户提交的所有的问题id161 post_id_list = [i.get("id") for i in post_data_list if i.get("id")]162 # print(post_id_list,"post_id_list") #['1', '2', '1', '2', '1', '2', '1', '2'] post_id_list163 #找到数据库中的所有的问题id164 question_id_list = [i.id for i in question_list]165 # print(question_id_list,"question_id_list") #[1, 2] question_id_list166 #数据库中的那些id需要删除(数据库里有前端没有的数据删除)167 del_id_list = set(question_id_list).difference(post_id_list)168 169 #循环ajax发过来的那些问题列表,170 for item in post_data_list:171 #item就是用户传进来的每个问题172 caption = item.get("caption")173 type_id = item.get("type_id")174 qid = item.get("id")175 options = item.get("options")176 if not qid in question_id_list:177 #如果前端传进来的id不在数据库里面,就说明要新增178 new_question_obj = models.Questions.objects.create(caption=caption,question_type=type_id,questionnaire_id=nid)179 if type_id==2:180for op in options:181 name = op.get("name")182 score = op.get("score")183 models.Option.objects.create(name=name,score=score,question=new_question_obj)184 else:185 #否则说明是要更新186 models.Questions.objects.filter(id=qid).update(caption=caption,question_type=type_id,questionnaire_id=qid)187 if not options:188#如果没有options就把数据库的options记录给删除了189models.Option.objects.filter(id=nid).delete()190 else:191#如果有先删除原来的后创建新传进来的192models.Option.objects.filter(id=nid).delete()193for op in options:194 name = op.get("name")195 score = op.get("score")196 models.Option.objects.create(name=name,score=score,question_id=qid)197 models.Questions.objects.filter(id__in=del_id_list).delete()198except Exception as e:199 ret['msg'] = str(e)200 ret["status"] = False201return JsonResponse(ret)202 203 204 class StudentForm(ModelForm):205# password = fields.CharField(max_length=8, validators=[RegexValidator("\d+", "密码只能是数字")],206# error_messages={"max_length":"8"}207# )208# 这里如果写上password,下面也有了,就会把下面的给覆盖了209class Meta:210 model=models.Student211 fields=["name","password"]212 213 error_messages ={214 "name":{"required":"用户名不能为空"},215 "password":{"required":"密码不能为空","max_length":"密码长度不能大于8位"},216 },217 widgets = {218 "password": widgets.PasswordInput(attrs={'placeholder': 'password', 'class': 'form-control'}),219 "name": widgets.TextInput(attrs={'placeholder': 'username', 'class': 'form-control'})220 }221 222 223 def student_login(request):224# obj = models.Student.objects.all().first()225# print(obj.id,obj.name)226if request.method=="GET":227 form = StudentForm()228else:229 print("============")230 form = StudentForm(data=request.POST)231 if form.is_valid():232 print("======",form.cleaned_data)233 user = models.Student.objects.filter(**form.cleaned_data).first()234 if user:235 request.session["id"] =user.id236 request.session["user"] =user.name237 class_id = request.session.get("class_id")238 qn_id = request.session.get("qn_id")239 # if class_id==None or qn_id==None:240 # return redirect("/index/")241 return redirect('/score/%s/%s'%(class_id,qn_id))242 else:243 return render(request,"student_login.html",{"form":form})244return render(request, "student_login.html", {"form": form})245 246 247 def func(val):248#参数要有,Form用正则匹配的时候不用加括号,自己就会执行这个函数,去验证249if len(val)<15:250 raise ValidationError("字数不能小于15字")251 252 def score(request,class_id,qn_id):253# print(class_id,qn_id)254student_id = request.session.get("id")255print(student_id,"student_id")256request.session["class_id"] = class_id257request.session["qn_id"] = qn_id258if not student_id:259 return redirect("/student_login/")260#查看当前用户是否是要评论的班级的学生261 262stu1 = models.Student.objects.filter(cls=class_id,id=student_id).count()263print("stu1",stu1)264if not stu1:265 return HttpResponse("你还不是这个班的学生呢,你无权访问我们这次问卷")266 267#当前学生是否已经评论过当前问卷268stu2 = models.Answer.objects.filter(student_id=student_id,queston__questionnaire_id=qn_id).count()269# print(stu2)270if stu2:271 return HttpResponse("你已经答过了,感谢你的参与。无法再进行第二次答卷")272 273#验证通过以后就开始展示答卷的页面了274# 展开当前问卷下的所有的问题275question_list = models.Questions.objects.filter(questionnaire_id=qn_id)276question_dict = {}277for que in question_list:278 print(que.id)279 print("asssdsfsfs",models.Option.objects.filter(question_id=que.id).values_list('id', 'name'))280 # que是每一个问题281 if que.question_type==1: #打分282 question_dict["val_%s"%que.id] = fields.ChoiceField(283 label=que.caption,284 error_messages={"required":"不能为空"},285 widget = widgets.RadioSelect,286 choices = [(i,i) for i in range(1,11)]287 )288 elif que.question_type==2: #单选289 question_dict["option_id_%s"%que.id] = fields.ChoiceField(290 label=que.caption,291 error_messages={"required":"不能为空"},292 widget = widgets.RadioSelect,293 choices=models.Option.objects.filter(question_id=que.id).values_list('id', 'name') #拿自己的选项294 )295 296 else: #评价297 question_dict["content_%s"%que.id] = fields.CharField(298 label=que.caption,299 error_messages={"required": "不能为空"},300 widget=widgets.Textarea,301 validators=[func,] #这里的func不用加参数302 )303 304MyTestForm = type("MyTestForm",(Form,),question_dict) #三个参数分别是:类名,继承的父类,后面是一个字典305if request.method =="GET":306 form = MyTestForm()307 return render(request,"score.html",{"question_list":question_list,"form":form})308else:309 form = MyTestForm(request.POST)310 if form.is_valid():311 #如果验证成功312 print(form.cleaned_data,"2222222")313 objs = []314 for key,v in form.cleaned_data.items():315 print(key,v,"1111111")316 k,qid = key.rsplit('_',1)317 print(k,qid,"2223333")318 answer_dict = {'student_id':student_id,'queston_id':qid,k:v}319 320 objs.append(models.Answer(**answer_dict))321 models.Answer.objects.bulk_create(objs)322 return HttpResponse("感谢你的参与!!")323 return render(request, "score.html", {"question_list": question_list, "form": form})

views.py

templates

1 <!DOCTYPE html>2 <html lang="en">3 <head>4<meta charset="UTF-8">5<meta http-equiv="X-UA-Compatible" content="IE=edge">6<meta name="viewport" content="width=device-width">7<title>Title</title>8<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">9<link rel="stylesheet" href="/static/css/index.css">10<link rel="stylesheet" href="/static/css/questionedit.css">11<script src="/static/jquery-3.2.1.min.js"></script>12<script src="/jquery-cookie/1.4.1/jquery.cookie.js"></script>13<script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>14 </head>15 <body>16 {#导航条#}17 <nav class="navbar label-primary">18<div class="container-fluid">19 <!-- Brand and toggle get grouped for better mobile display -->20 <div class="navbar-header">21 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"22 data-target="#bs-example-navbar-collapse-1" aria-expanded="false">23 <span class="sr-only">Toggle navigation</span>24 <span class="icon-bar"></span>25 <span class="icon-bar"></span>26 <span class="icon-bar"></span>27 </button>28 <a class="navbar-brand textstyle" href="#">CRM系统</a>29 </div>30 31 <!-- Collect the nav links, forms, and other content for toggling -->32 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">33 <ul class="nav navbar-nav">34 <li class="active"><a href="#" class="textstyle">平台首页 <span class="sr-only">(current)</span></a></li>35 <li><a href="#" class="textstyle">资产首页</a></li>36 </ul>37 <form class="navbar-form navbar-left">38 <div class="form-group">39 <input type="text" class="form-control" placeholder="Search">40 </div>41 <button type="submit" class="btn btn-default">Submit</button>42 </form>43 </div><!-- /.navbar-collapse -->44</div><!-- /.container-fluid -->45 </nav>46 <div class="container-fluid">47<div class="row">48 <div class="left">49 <div class="col-md-3"></div>50 </div>51 <div class="right">52 <div class="col-md-9">53 <div class="panel panel-default">54 <div class="panel-heading"><a href="">首页</a>/数据列表</div>55 <div class="panel-body">56 {% block content %}57 58 {% endblock %}59 </div>60 </div>61 </div>62 </div>63</div>64 </div>65 </body>66 </html>

base.html

1 {% extends "base.html" %}2 3 {% block content %}4<button class="btn btn-success addBtn">添加</button>5<table class="table table-bordered active">6 <thead>7 <th><input type="checkbox"></th>8 <th>问卷调查名称</th>9 <th>问卷调查班级</th>10 <th>参与人数</th>11 <th>问卷选项</th>12 <th>调查地址</th>13 <th>查看评分</th>14 <th>操作</th>15 </thead>16 <tbody>17 {% for Questionnaire in Questionnaire_obj %}18 <tr>19 <td><input type="checkbox"></td>20 <td>{{ Questionnaire.title }}</td>21 <td>{{ Questionnaire.cls.title }}</td>22 <td>{{ Questionnaire.part_num }}/{{ Questionnaire.cls.student_set.all.count }}</td>23 <td><a href="/questionedit/{{ Questionnaire.id }}/">编辑问卷</a></td>24 <td><a href="/score/{{ Questionnaire.cls.id }}/{{ Questionnaire.id }}/">/score/{{ Questionnaire.cls.id }}/{{ Questionnaire.id }}/</a></td>25 <td><a href="">查看评分</a></td>26 <td><a href=""><button class="btn btn-danger">删除</button></a></td>27 </tr>28 {% endfor %}29</table>30 {% endblock %}

index.html

1 {% extends "base.html" %}2 {% block content %}3<div class="pull-right">4 <button class="btn btn-success addquestion">添加</button>5 <button class="btn btn-info savebtn">保存</button>6</div>7<div class="ccc">8 <ol>9 {% for item in form %}10 <li>11 <div class="glyphicon glyphicon-remove pull-right delquestion"></div>12 <div pk="{{ item.obj.id }}">13{#<p>{{ item.form }}</p>#}14<p>问题名称:{{ item.form.caption }}</p>15<p class="name">类型名称:{{ item.form.question_type }}16 <a class="{{ item.option_class }} addoption">添加选项</a>17</p>18<ul>19 {% for v in item.options %}20 <li class="{{ v.obj.id }}">{{ v.form }}21 <span class="glyphicon glyphicon-remove deloption"></span>22 </li>23 {% endfor %}24</ul>25 </div>26 </li>27 {% endfor %}28 </ol>29</div>30<script>31 //添加选项32 $(".ccc").on("click", ".addoption", function () {33 var ele_ul = $(this).parent().parent().children("ul");34 var s = '<li"><label for="id_name">选项名:</label><input type="text" name="name" maxlength="32" required="" id="id_name"><label for="id_score">选项对应的分值:</label><input type="number" name="score" required="" id="id_score"><span class="glyphicon glyphicon-remove deloption"></span></li>';35 ele_ul.append(s)36 37 });38 39 //删除选项(绑定事件委派)40 $('.ccc').on('click', '.deloption', function () {41 //找到当前的那一行删除42 $(this).parent().remove()43 });44 45 //删除问题(添加事件委派)46 $("ol").on('click', ".delquestion", function () {47 console.log($("body"));48 $(this).parent().remove()49 });50 51 //改变下拉框的触发不同的事件52 $(".ccc").on("click", "#id_question_type", function () {53 if ($(this).val() == 2) {54 //如果是单选的时候,如果有选项就把下面的内容隐藏了55 $(this).next().removeClass("hide");56 }57 else {58 //否则就隐藏添加选项,吧西面的内容清空59 $(".addoption").addClass("hide");60 $(this).parent().next().empty()61 }62 });63 64 //添加问题65 $(".addquestion").click(function () {66 //克隆一个整个的67 var s = $("ol").children("li:last").clone();68 $("ol").append(s);69 });70 //保存修改的信息71 plist = [];72 $(".savebtn").click(function () {73 $("ol>li").each(function (i,v) {74 {# console.log(i,v); //v打印的是每一个li#}75 var id =$(this).find("div").eq(1).attr("pk");76 var caption = $(v).find("textarea").val();77 var type_id = $(v).find("select").val();78 console.log($(v).find("select"),type_id);79 if (type_id==2){80 //如果类型id是2的时候,说明是有option的81 var options_list = [];82 var li = $(v).find("li");83 li.each(function (i,v) {84 {#console.log(i,v);#}85 var option_id = $(this).attr("class");86 var option_name =$(this).find("input:first").val();87 var option_score =$(this).find("input:last").val();88 options_list.push({"option_id":option_id,"option_name":option_name,"option_score":option_score})89 });90 plist.push({"id":id,"caption":caption,"type_id":type_id,"options":options_list});91 }92 else {93 plist.push({"id":id,"caption":caption,"type_id":type_id});94 }95 });96 $.ajax({97 {#url: "/questionsave/"+s+"/",#}98 url:"/questionsave/{{ nid }}/",99 type: "post",100 data: JSON.stringify(plist),101 contentType: "json",102 headers: {"X-CSRFToken": $.cookie('csrftoken')},103 success: function (i, v) {104 console.log(i, v);105 location.href = "/index/"106 }107 })108 })109 110</script>111 {% endblock %}

questionedit.html

1 <!DOCTYPE html>2 <html lang="en">3 <head>4<meta charset="UTF-8">5<meta http-equiv="X-UA-Compatible" content="IE=edge">6<meta name="viewport" content="width=device-width">7<title>Title</title>8<style>9 li{10 list-style-type: none;11 }12 ul li{13 display: inline-block;14 }15</style>16 </head>17 <body>18 <form action="" method="post" novalidate>19{% csrf_token %}20{% for foo in form %}21<p>{{ foo.label }}{{ foo }}{{ foo.errors.0 }}</p>22{% endfor %}2324<input type="submit" value="提交">25 </form>26 </body>27 </html>

score.html

1 <!DOCTYPE html>2 <html lang="en">3 <head>4<meta charset="UTF-8">5<meta http-equiv="X-UA-Compatible" content="IE=edge">6<meta name="viewport" content="width=device-width">7<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">8<title>Title</title>9<style>10 .container{11 margin-top: 50px;12 }13</style>14 </head>15 <body>16 <div class="container">17<div class="row">18 <div class="col-md-4 col-md-offset-3">19 <form action="" method="post" novalidate>20 {% csrf_token %}21{% for foo in form %}22<p>{{ foo.label }}{{ foo }}{{ foo.errors.0 }}</p>23{% endfor %}24 25 <button type="submit" class="btn btn-primary">登录</button>26 </form>27 </div>28</div>29 </div>30 </body>31 </html>

student_login

如果觉得《调查问卷表结构设计及具体实现》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。