1. 程式人生 > 實用技巧 >029 調查問卷相關與調查問卷表結構設計及具體實現

029 調查問卷相關與調查問卷表結構設計及具體實現

調查問卷相關

1、問卷的儲存按鈕
前端通過ajax把資料發過來後端處理資料,然後返回給前端
2、對問卷做答
首先使用者進行登入,驗證
條件:1、只有本班的學生才能對問卷做答
2、已經參加過的不能再次訪問

在前端顯示的樣式
顯示當前問卷的問題
- 你對近期的學習有哪些意見、。?
1 2 3 4 5 。。 10
- 路寧女朋友一些建議?
文字...
- 路寧選擇帽子顏色?
A. 綠色 B.翠綠
C. 墨綠 D.深綠色

問卷的儲存按鈕涉及到的知識點:
集合的操作:

   s = [1,4,5,8]
    s2 = [2,4,7,8,6]
    print(set(s).difference(s2))  #
做差集,在s中找和s2不同的元素 {1, 5} print(set(s2).difference(s)) #做差集,在s2中找和s不同的元素 {2, 6, 7} print(set(s)-set(s2)) #這種方式和上面的一樣 {1, 5} print(set(s2)^set(s)) #交集 {1, 2, 5, 6, 7} print(set(s2)|set(s)) #並集 {1, 2, 4, 5, 6, 7, 8}

思路分析:
拿到前端的資料,像下面這種格式的
如果是json格式發的,注意要在request.body中取值。


ajax_post_list = [
{
'id': 2,
'caption': "魯寧愛不是番禺??",
'tp': 1,

},
{
'id': None,
'caption': "八級哥腎好不好?",
'tp': 3
},
{
'id': None,
'caption': "魯寧臉打不打?",
'tp': 2,
"options": [
{'id': 1, 'name': '綠', 'score': 10},
{'id': 2, 'name': '翠綠', 'score': 8},
]
},
]
前端的資料和資料庫的資料進行比較,
- 前端有後端沒有要新增
- 前端沒有後端有要刪除
- 前端有後端也有要更新

#資料庫中的那些問題id需要刪除(資料庫裡有前端沒有的資料刪除)採用集合操作,求差集
del_id_list = set(question_id_list).difference(post_id_list) #del_id_list就是要刪除的id
迴圈前端發過來的資料,得到資料依次進行比較,
#判斷前端傳進來的id不在資料庫裡面,就說明要新增
#如果發過來的ty_id是2(單選)的時候,也要新增
#否則就是要更新
#更新的時候注意也要判斷一下ty_id,如果沒有的話就的吧資料庫的刪除了,如果有的話
#就先吧資料庫的刪除了,然後建立更新

問卷的問卷做答涉及到的知識點:
1、建立類的兩種方式
方式一:
class Foo(object):
x1=5
def func(self,arg):
return arg
方式二:
Foo = type('Foo',(object,),{"x1":5,"func":lambda x:x})
有與Python中一切皆物件,所以累也是一個物件,它是type的物件,所以這裡就可以例項化
這裡的三個引數分別是,:類名,繼承的類,字典裡面可以放靜態屬性也可以放方法等。

2、split切割
s = "aaaa_ssss_ddd"
print(s.split("_")) #['aaaa', 'ssss', 'ddd']
print(s.split("_",1)) #['aaaa', 'ssss_ddd'] #這裡的引數1代表式按第一個下劃線分割
print(s.rsplit("_",1)) #['aaaa_ssss', 'ddd'] #rsplit表示從右邊的第一個下劃線分割

3、Form前端迴圈
views.py
class LoginForm(Form):
name = ...
pwd = ...

def login(request):
form = LoginForm()
return render(request,"login.html")

login.html
不用迴圈實現的、
<div>
{{ form.name }} {{ form.errors.name.0 }}
{{ form.aee }} {{ form.errors.age.0 }}
</div>

用迴圈實現的、
<div>
{% for item in form %}
{{ item.label }}{{ item }}{{ item.errors.0 }}
input框前的文字----每個input框----錯誤提示
{% endfor %}
</div>
4、自定義Form驗證規則
def func(val):
if len(val) < 15:
raise ValidationError('你太短了')


class LoginForm(Form):
name1和name2是一樣的,只是兩種表示的方式
name1 = fields.CharField(label='xxx', widget=widgets.Textarea, validators=[RegexValidator(regex=""),])
name2 = fields.RegexField(label='xxx', widget=widgets.Textarea, regex="xxx")

如果上面的驗證不滿足你需求的時候,可以用這一種。
注意: validators=[func, ]這裡的func函式不加(),Form會自動找到這個函式去執行它
name3 = fields.CharField(label=que.caption, widget=widgets.Textarea, validators=[func, ])

也可以自己去定義鉤子函式去驗證
def clean_name1(self,val):
return val



具體操作:
首先使用者得先登入
#先判斷哪些人可以答卷
檢視當前登入使用者是否是要評論的班級的學生
models.Student
如果不是就返回無權訪問,

#是否已經提交過當前問卷的答案

#展示當前問卷下的所有的問題









調查問卷表結構設計及具體實現

一、表結構設計

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 <!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="https://cdn.bootcss.com/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 %}
23     
24     <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