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

一、表结构设计

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.username
    class Meta:
        verbose_name_plural="员工表"

class ClassList(models.Model):
    '''班级表'''
    title = models.CharField(max_length=32,verbose_name="班级名")
    def __str__(self):
        return self.title
    class 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.name

    class 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.title

    class 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.caption

    class 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.content

    class 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 url
 2 from django.contrib import admin
 3 from app01 import views
 4 urlpatterns = [
 5     url(r'^admin/', admin.site.urls),
 6     url(r'^index/$', views.index),
 7     url(r'^questionedit/(\d+)/$', views.questionedit),
 8     url(r'^questionedit2/(\d+)/$', views.questionedit2),
 9     url(r'^questionsave/(\d+)/$', views.questionsave),
10     url(r'^student_login/$', views.student_login),
11     url(r'^score/(\d+)/(\d+)/$', views.score),
12 ]
urls.py

 

views.py

  1 from django.core.validators import RegexValidator
  2 from django.db.models.aggregates import Count
  3 from django.forms.forms import Form
  4 from django.http.response import JsonResponse
  5 from django.shortcuts import render, HttpResponse,redirect
  6 from app01 import models
  7 from django.forms import ModelForm,fields,widgets
  8 import json
  9 from django.core.exceptions import ValidationError
 10 from django.core.validators import RegexValidator
 11 # Create your views here.
 12 def index(request):
 13     Questionnaire_obj = models.Questionnaire.objects.all()
 14     #查询问卷所属的班级的学生个数
 15     for 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)
 18     return render(request,"index.html",{"Questionnaire_obj":Questionnaire_obj})
 19 
 20 class QuestionForm(ModelForm):
 21     class Meta:
 22         model = models.Questions
 23         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):
 33     class Meta:
 34         model = models.Option
 35         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 form
 63     #     else:
 64     #         '''已经创建了问题的'''
 65     #         for que in que_list:
 66     #             form = QuestionForm(instance=que)
 67     #             yield form
 68     # 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_list
 95     #             yield temp
 96     # return render(request, "questionedit.html", {"form": inner()})
 97 
 98     # 方式四
 99     def 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):
116                         option_list = models.Option.objects.filter(question=quee)
117                         for v in option_list:
118                             yield {"form":OptionModelForm(instance=v),"obj":v}
119                     temp["options"] = inner_loop(que)
120                 yield temp
121     return 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                         '''如果选项类型是单选的时候'''
138                         temp["option_class"] = ""
139 
140                         # 如果是单选的时候让显示所有的选项
141                         def 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 
146                         temp["options"] = inner_loop(que)
147                     yield temp
148         return render(request,"questionedit.html",{"form":inner()})
149 
150 
151 def questionsave(request,nid):
152     ret = {"status":True,"msg":None,"data":None}
153     try:
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             #找到用户提交的所有的问题id
161             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_list
163             #找到数据库中的所有的问题id
164             question_id_list = [i.id for i in question_list]
165             # print(question_id_list,"question_id_list")  #[1, 2] question_id_list
166             #数据库中的那些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:
180                         for 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记录给删除了
189                         models.Option.objects.filter(id=nid).delete()
190                     else:
191                         #如果有先删除原来的后创建新传进来的
192                         models.Option.objects.filter(id=nid).delete()
193                         for 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()
198     except Exception as e:
199         ret['msg'] = str(e)
200         ret["status"] = False
201     return 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,下面也有了,就会把下面的给覆盖了
209     class Meta:
210         model=models.Student
211         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)
226     if request.method=="GET":
227         form = StudentForm()
228     else:
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.id
236                 request.session["user"] =user.name
237                 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})
244     return render(request, "student_login.html", {"form": form})
245 
246 
247 def func(val):
248     #参数要有,Form用正则匹配的时候不用加括号,自己就会执行这个函数,去验证
249     if len(val)<15:
250         raise ValidationError("字数不能小于15字")
251 
252 def score(request,class_id,qn_id):
253     # print(class_id,qn_id)
254     student_id = request.session.get("id")
255     print(student_id,"student_id")
256     request.session["class_id"] = class_id
257     request.session["qn_id"] = qn_id
258     if not student_id:
259         return redirect("/student_login/")
260     #查看当前用户是否是要评论的班级的学生
261 
262     stu1 = models.Student.objects.filter(cls=class_id,id=student_id).count()
263     print("stu1",stu1)
264     if not stu1:
265         return HttpResponse("你还不是这个班的学生呢,你无权访问我们这次问卷")
266 
267     #当前学生是否已经评论过当前问卷
268     stu2 = models.Answer.objects.filter(student_id=student_id,queston__questionnaire_id=qn_id).count()
269     # print(stu2)
270     if stu2:
271         return HttpResponse("你已经答过了,感谢你的参与。无法再进行第二次答卷")
272 
273     #验证通过以后就开始展示答卷的页面了
274     # 展开当前问卷下的所有的问题
275     question_list = models.Questions.objects.filter(questionnaire_id=qn_id)
276     question_dict = {}
277     for 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 
304     MyTestForm = type("MyTestForm",(Form,),question_dict)  #三个参数分别是:类名,继承的父类,后面是一个字典
305     if request.method =="GET":
306         form = MyTestForm()
307         return render(request,"score.html",{"question_list":question_list,"form":form})
308     else:
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 
 2 "en">
 3 
 4     "UTF-8">
 5     "X-UA-Compatible" content="IE=edge">
 6     "viewport" content="width=device-width">
 7     Title
 8     "stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
 9     "stylesheet" href="/static/css/index.css">
10     "stylesheet" href="/static/css/questionedit.css">
11     
12     
13     
14 
15 
16 {#导航条#}
17 
46 
class="container-fluid"> 47
class="row"> 48
class="left"> 49
class="col-md-3">
50
51
class="right"> 52
class="col-md-9"> 53
class="panel panel-default"> 54
class="panel-heading">"">首页/数据列表
55
class="panel-body"> 56 {% block content %} 57 58 {% endblock %} 59
60
61
62
63
64
65 66
base.html

 

 1 {% extends "base.html" %}
 2 
 3 {% block content %}
 4     
 5     class="table table-bordered active">
 6 7 8 91011121314151617         {% for Questionnaire in Questionnaire_obj %}
1819202122232425262728         {% endfor %}
29
"checkbox"> 问卷调查名称 问卷调查班级 参与人数 问卷选项 调查地址 查看评分 操作
"checkbox"> {{ Questionnaire.title }} {{ Questionnaire.cls.title }} {{ Questionnaire.part_num }}/{{ Questionnaire.cls.student_set.all.count }} "/questionedit/{{ Questionnaire.id }}/">编辑问卷 "/score/{{ Questionnaire.cls.id }}/{{ Questionnaire.id }}/">/score/{{ Questionnaire.cls.id }}/{{ Questionnaire.id }}/ "">查看评分 "">
30 {% endblock %}
index.html

 

  1 {% extends "base.html" %}
  2 {% block content %}
  3     
class="pull-right"> 4 5 6
7
class="ccc"> 8
    9 {% for item in form %} 10
  1. 11
    class="glyphicon glyphicon-remove pull-right delquestion">
    12
    "{{ item.obj.id }}"> 13 {#

    {{ item.form }}

    #}
    14

    问题名称:{{ item.form.caption }}

    15

    class="name">类型名称:{{ item.form.question_type }} 16 class="{{ item.option_class }} addoption">添加选项 17

    18
      19 {% for v in item.options %} 20
    • class="{{ v.obj.id }}">{{ v.form }} 21 class="glyphicon glyphicon-remove deloption"> 22
    • 23 {% endfor %} 24
    25
    26
  2. 27 {% endfor %} 28
29
30 111 {% endblock %}
questionedit.html

 

 1 
 2 "en">
 3 
 4     "UTF-8">
 5     "X-UA-Compatible" content="IE=edge">
 6     "viewport" content="width=device-width">
 7     Title
 8     
16 
17 
18 
"" method="post" novalidate> 19 {% csrf_token %} 20 {% for foo in form %} 21

{{ foo.label }}{{ foo }}{{ foo.errors.0 }}

22 {% endfor %} 23 24 "submit" value="提交"> 25
26 27
score.html

 

 1 
 2 "en">
 3 
 4     "UTF-8">
 5     "X-UA-Compatible" content="IE=edge">
 6     "viewport" content="width=device-width">
 7     "stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
 8     Title
 9     
14 
15 
16 
class="container"> 17
class="row"> 18
class="col-md-4 col-md-offset-3"> 19
"" method="post" novalidate> 20 {% csrf_token %} 21 {% for foo in form %} 22

{{ foo.label }}{{ foo }}{{ foo.errors.0 }}

23 {% endfor %} 24 25 26
27
28
29
30 31
student_login

 

转载于:https://www.cnblogs.com/haiyan123/p/8016924.html

你可能感兴趣的:(json,数据库,python)