問卷調查

 

 

問卷調查

  問卷調查也能夠成爲滿意度調查,是公司中針對每一個用戶開發的調查的功能。其目的能夠是針對員工合格與否的調查也能夠是對某個項目或者活動進行的意見調查。javascript

表關係建立

  這裏用的是班級中學生的調查狀況,也能夠用於公司裏部門的調查css

一共6張表html

from django.db import models
class UserInfo(models.Model):
    """
    員工表
    """
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name

class ClassList(models.Model):
    """
    班級表
    """
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title

class Student(models.Model):
    """
    學生表
    """
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    cls = models.ForeignKey(to=ClassList)

    def __str__(self):
        return self.user


class Questionnaire(models.Model):
    """
    問卷表
    """
    title = models.CharField(max_length=64)
    cls = models.ForeignKey(to=ClassList)
    creator = models.ForeignKey(to=UserInfo)

    def __str__(self):
        return self.title

class Question(models.Model):
    """
    問題
    """
    caption = models.CharField(max_length=64)

    question_types = (
        (1,'打分'),
        (2,'單選'),
        (3,'評價'),
    )
    tp = models.IntegerField(choices=question_types)
    naire = models.ForeignKey(Questionnaire,default=1)


    def __str__(self):
        return self.caption

class Option(models.Model):
    """
    單選題的選項
    """
    name = models.CharField(verbose_name='選項名稱',max_length=32)
    score = models.IntegerField(verbose_name='選項對應的分值')
    qs = models.ForeignKey(to=Question)

    def __str__(self):
        return self.name

class Answer(models.Model):
    """
    回答
    """
    stu = models.ForeignKey(to=Student)
    question = models.ForeignKey(to=Question)

    option = models.ForeignKey(to="Option",null=True,blank=True)
    val = models.IntegerField(null=True,blank=True)
    content = models.CharField(max_length=255,null=True,blank=True)
    def __str__(self):
        return self.stu
models.py

 

路由分發

  這裏依舊沒有寫註銷的功能,登陸功能也較爲簡單前端

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^log_in/$',views.log_in ),
    url(r'^index/$',views.index ),
    url(r'^$',views.index ),
    url(r'^edit/(\d+)/$',views.edit ),#編輯問卷
    url(r'^score/(\d+)/(\d+)/$', views.score),#填寫問卷

]

 

登陸功能

def log_in(request):
    if request.method=="POST":
        user=request.POST.get("user")
        pwd=request.POST.get("pwd")
        obj=models.Student.objects.filter(user=user,pwd=pwd)
        print(obj)
        if obj:
            return redirect('/index/')
        else:
            return HttpResponse('錯誤')

    return render(request,'log_in.html')
views.py 中
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>login</title>
</head>
<body>

<form action="" method="post">
    {% csrf_token %}
    user:<input type="text">
    pwd:<input type="password">
    <input type="submit">

</form>


</body>
</html>
log_in.html

 

首頁

def index(request):
    q_all=models.Questionnaire.objects.all()#全部的問卷
    cls_all=models.ClassList.objects.all()#全部的班級(部門)
    stu_all=models.Student.objects.all()#全部的學生(員工)
    return render(request,'index.html',{'q_all':q_all,'cls_all':cls_all,'stu_all':stu_all})
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>index</title>
    <script src="/static/jquery-3.2.1.min.js"></script>

    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <style>
        .p1 ul li {
            list-style: none;
            color: white;
            float: left;
            margin-right: 40px;
            padding-bottom: 30px;
        }


    </style>
    
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">CRM系統</h3>
                </div>
                <div class="panel-body">
                    <p>xxxxxxxxxx</p>
                    <p>xxxxxxxxxx</p>
                    <p>xxxxxxxxxx</p>
                    <p>xxxxxxxxxx</p>
                    <p>xxxxxxxxxx</p>
                    <p>xxxxxxxxxx</p>
                    <p>調查問卷列表</p>
                </div>
            </div>
        </div>
        <div class="col-md-10">
            <div class="panel panel-default ">
                <div class="panel-heading p1">
                    <ul>
                        <li><a href="">平臺首頁</a></li>
                        <li><a href="">資產首頁</a></li>
                    </ul>
                    <div class="pull-right">
                        <ul>
                            <li><a href="">任務</a></li>
                            <li><a href="">通知</a></li>
                            <li><a href="">消息</a></li>
                        </ul>
                    </div>
                </div>
            
            
                <div class="panel-body">
                    <div class="panel panel-default">
                        <div class="panel-heading">
                            <h3 class="panel-title">首頁/數據列表</h3>
                        </div>
                        <div class="panel-body">
                            <button class="btn btn-success">添加</button>
                            <table class="table table-bordered">
                                <th>
{#                            <td><input type="checkbox"></td>#}
                                <td>調查問卷名稱</td>
                                <td>問卷調查班級</td>
                                <td>參與人數</td>
                                <td>問卷選項</td>
                                <td>調查地址</td>
                                <td>查看評分</td>
                                <td>操做</td>
                                </th>
                                {% for q in q_all %}
                                    <tr>
                                        <td><input type="checkbox"></td>
                                        <td><a href="">{{ q.title }}</a></td>
                                        <td>{{ q.cls.title }}</td>
                                        <td>0/{{ q.cls.student_set.count }}</td>
                                        <td><a href="/edit/{{ q.id }}/">編輯問卷</a></td>
                                        <td><a href="">xxxxxxxxxxx</a></td>
                                        <td><a href="">查看評分</a></td>
                                        <td><a href="">刪除</a></td>
                                    </tr>
                                {% endfor %}
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


</body>
</html>
index.html

 

編輯問卷

  這裏須要用到modelform組件,咱們在app文件夾下建立一個form.py文件,專門用來放置form組件java

from django.forms import ModelForm

class QuestionModelForm(ModelForm):
    class Meta:
        model = models.Question
        fields = ['caption','tp']
        error_messages = {
            'caption': {'required': '不能爲空', 'invalid': '格式錯誤'}
        }
        widgets = {
            'caption': wd.Input(attrs={'class': 'form-control caption_input',"style":"height: 40px"}),
            'tp': wd.Select(attrs={'class': 'form-control tp',"style":"width: 120px",})
        }


class OptionModelForm(ModelForm):
    class Meta:
        model = models.Option
        fields = ['name','score']
        widgets = {
            'name': wd.Input(attrs={'class': '',"style":"width: 80px"}),
            'score': wd.Input(attrs={'class': '',"style":"width: 80px"})
        }
form.py中的 QuestionModelForm 和 OptionModelForm

  由於這裏的數據,後端進行循環後傳遞給前端,前端還需繼續循環,因此這裏咱們用到生成器。後端每一次循環後yeild惰性循環,待前端須要時在進行循環,減少數據庫操做規模、節省內存。jquery

  注意:前端頁面對問卷的增長和刪除須要用到事件委派。保存按鈕提交的信息中,須要區分出點了添加按鈕後又刪掉的問題,這種問題就不要讓他跑數據庫啦,直接不進行操做就行了ajax

def edit(request,pid):
    # if request.is_ajax():
    #     edit_form = Question_form()
    #     response={'form':edit_form}
    #     return HttpResponse(json.dumps(response))
    #
    # edit_form=Question_form()
    # edit_obj=models.Questionnaire.objects.get(id=id)
    # return render(request,'edit.html',{'edit_obj':edit_obj,'edit_form':edit_form})


    """
    問題
    :param request:
    :param pid: 問卷ID
    :return:
    """
    if request.method=='GET':
        print('編輯問卷頁面')
        def inner():
            que_list = models.Question.objects.filter(naire_id=pid)  # [Question,Question,Question]
            if not que_list:
                # 新建立的問卷,其中還麼有建立問題
                form = QuestionModelForm()
                yield {'form': form, 'obj': None, 'option_class': 'hide', 'options': None}
            else:
                # 含問題的問卷
                for que in que_list:
                    form = QuestionModelForm(instance=que)
                    temp = {'form': form, 'obj': que, 'option_class': 'hide', 'options': None}
                    if que.tp == 2:#是選擇類型
                        temp['option_class'] = ''
                        temp['add_a'] = '添加選項'#前端生成按鈕
                        temp['add_pic'] = 'glyphicon glyphicon-plus add-ques'#圖標

                        # 獲取當前問題的全部選項que
                        def inner_loop(quee):
                            option_list = models.Option.objects.filter(qs=quee)
                            for v in option_list:
                                yield {'form': OptionModelForm(instance=v), 'obj': v}

                        temp['options'] = inner_loop(que)
                    yield temp

        return render(request, 'edit.html', {'form_list': inner(),'pid':pid})

    else:
        print('~~~~~~~~~~~~~保存問卷中')
        ret = {'status': True, 'msg': None, 'data': None}
        try:
            # 新提交的數據:
            plist=json.loads(request.POST.get('plist'))
            for item in plist:
                item['id']=int(item.get('id'))
                item['tp']=int(item.get('tp'))

                if len(item['options'])>0:
                    for i in item['options']:
                        i['id']=int(i['id'])
                        i['score']=int(i['score'])
            print('轉義後的問題',plist)
            # 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},
            #         ]
            #     },
            # ]

            question_list = models.Question.objects.filter(naire_id=pid)

            # 用戶提交的全部問題ID
            post_id_list = [i.get('id') for i in plist if i.get('id')]
            print('用戶提交的全部問題ID',post_id_list)

            # 數據庫中獲取的如今已有的問題ID
            question_id_list = [i.id for i in question_list]
            print('數據庫中獲取的如今已有的問題ID',question_id_list)

            # 數據庫中的那些ID須要刪除?
            del_id_list = set(question_id_list).difference(set(post_id_list))

            print('數據庫中的那些ID須要刪除',del_id_list)

            # 循環ajax提交過來的全部問題信息
            for item in plist:
                print(item)
                # item就是用戶提交過來的一個問題
                qid = item.get('id')
                caption = item.get('caption')
                tp = item.get('tp')
                options = item.get('options')
                print(qid,caption,tp,options)

                if qid not in question_id_list:
                    # 要新增
                    new_question_obj = models.Question.objects.create(caption=caption, tp=tp)
                    if tp == 2:
                        for op in options:
                            models.Option.objects.create(qs=new_question_obj, name=op.get('name'),
                                                         score=op.get('score'))
                    print('新增問題成功')

                else:
                    # 要更新
                    print('要更新',qid)
                    models.Question.objects.filter(id=qid).update(caption=caption, tp=tp)
                    print('更新非單選問題成功')

                    if not options:
                        #類型由單選改成了其餘類型,就須要將想關聯的選項刪除
                        models.Option.objects.filter(qs_id=qid).delete()
                        print('刪除選項成功')
                    else:
                        # 更新選項(不推薦)
                        models.Option.objects.filter(qs_id=qid).delete()
                        for op in options:
                            models.Option.objects.create(name=op.get("name"), score=op.get('score'), qs_id=qid)
                        print('更新選項成功')
            models.Question.objects.filter(id__in=del_id_list).delete()
        except Exception as e:
            ret['msg'] = str(e)
            ret['status'] = False
        print('保存問卷結束')
        return HttpResponse(json.dumps(ret))
views.py中的edit
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>編輯問卷題目</title>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <style>
        .head {
            background-color: #2e6da4;
            height: 30px;
            line-height: 30px;

        }

        .head div a {
            color: whitesmoke;
        }

        .head div {
            margin-right: 30px;
        }

        .col-md-2 {
            margin-right: -30px;
        }

        .menu {
            border: solid 1px grey;
            height: 800px;
        }

        .two-btn .btn {
            margin: 20px 0;
        }

        .two-btn {
            height: 80px;
        }

        form {
            padding: 20px 0;
        }

        .glyphicon-remove {
            padding: 20px;
        }

        {#        .question{#}
        {#            background:#dce7f4 ;#}
        {#        }#}
        ol {
            padding: 0;
            list-style: none;
            counter-reset: sectioncounter
        }

        ol > li:before {
            content: '問題' counter(sectioncounter) ':';
            counter-increment: sectioncounter;
            font-size: 18px;
            color: #d4d4d4;
        }

        ol > li:nth-of-type(odd) {
            background-color: #f9f9f9;
        }

        .tp {
            display: inline-block;
        }


    </style>


</head>
<body>


<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">
            <div class="head">
                <span>CRM系統</span>
            </div>
            <div class="menu">
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
                <div>xxxxxxxxxxxx</div>
            </div>
        </div>
        <div class="col-md-10">
            <div class="head">
                <div class="pull-left"><a href="">平臺首頁</a></div>
                <div class="pull-left"><a href="">資產首頁</a></div>
                <div class="pull-right"><a href="">任務</a></div>
                <div class="pull-right"><a href="">通知</a></div>
                <div class="pull-right"><a href="">消息</a></div>
            </div>
            <div class="content">
                <div class="two-btn">
                    <div class="pull-right">

                        <button class="btn btn-success " id="add-btn">添加</button>


                        <button class="btn btn-primary" id="save-btn">保存</button>

                    </div>
                </div>


                <ol class="que">
                    {% for item in form_list %}
                        <li pk="{{ item.obj.id }}">
                            <div class="question">
                                <div class="pull-right">
                                    <a href="javascript:;"><span class="glyphicon glyphicon-remove"></span></a>
                                </div>

                                <div class="row">
                                    <div class="col-md-8 col-md-offset-1">
                                        <div class="row">
                                            <form class="form-horizontal">
                                                {% csrf_token %}
                                                <div class="form-group">
                                                    <label class="col-sm-2 control-label">問題:</label>
                                                    <div class="col-sm-9">
                                                        {{ item.form.caption }}
                                                    </div>

                                                </div>
                                                <div class="form-group typeselect">
                                                    <label class="col-sm-2 control-label">類型:</label>
                                                    <div class="col-sm-10 type">
                                                        {{ item.form.tp }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                                        <a href="javascript:;"
                                                           class="{{ item.add_pic }} ">{{ item.add_a }}</a>
                                                        <ul>
                                                            {% for v in item.options %}
                                                              {#  選項#}
                                                                <li id="{{ v.obj.id }}">{{ v.form }}<a
                                                                        href="javascript:;"><span
                                                                        class="glyphicon glyphicon-remove"></span></a>
                                                                </li>
                                                            {% endfor %}
                                                        </ul>
                                                    </div>
                                                </div>

                                            </form>
                                        </div>
                                    </div>
                                </div>


                            </div>
                        </li>
                    {% endfor %}
                </ol>
            </div>
        </div>
    </div>
</div>


<script>
    //更改問題類型
    $('.que').on('change', '.tp', function () {
        var d = $(this).val()

        if (d == 2) {

            var x = '<a href="javascript:;" class="glyphicon glyphicon-plus">添加選項</a>'
            $(this).next().html('添加選項').attr({'class': 'glyphicon glyphicon-plus add-ques', 'href': 'javascript:;'})
            var s = '<li id="100100100010011111111">選項名稱:<input type="text" id="id_name"> 選項對應的分值:<input type="text" id="id_score"><a href="javascript:;"><span class="glyphicon glyphicon-remove"></span></a></li>'
            $(this).next().next().append(s)
        }
        else {
            $(this).next().next().children('li').remove()
            $(this).next().html('').attr({'class': ''})

        }

    })

    //添加選項
    $('.que').on('click', '.add-ques', function () {
        $(this).next().append('<li id="100100100010011111111">選項名稱:<input type="text" id="id_name"> 選項對應的分值:<input type="text" id="id_score"><a href="javascript:;"><span class="glyphicon glyphicon-remove"></span></a></li>')
    })

    //刪除選項
    $('.que').on('click', '.question .pull-right a', function () {
        $(this).parent().parent().parent().remove()
    })


    //刪除整個問題
    $('.que').on('click', '.typeselect li a', function () {
        $(this).parent().remove()
    })

    //添加問題
    $('#add-btn').click(function () {
        var li = $('.content>ol>li:first').clone(true)
        var a = '<a href="javascript:;" class=" "></a><ul></ul>'
        $('.content>ol').append(li)
        $('.content>ol>li:last').find('.caption_input').val('')
        $('.content>ol>li:last').find('select').value = 1
        $('.content>ol>li:last').find('select').next().html('')
        $('.content>ol>li:last').find('select').next().next().children('li').remove()
        $('.content>ol>li:last').attr('pk', '10010010001001')
    })


    //ajax提交

    //點擊保存按鈕獲得全部問題的數據
    var plist = [];
    $('#save-btn').click(function () {

        $('.content>ol>li').each(function () {
            var dic = {'id': undefined, 'caption': undefined, 'tp': undefined, 'options': []}
            console.log($(this).attr('pk'))
            dic['id'] = $(this).attr('pk');
            dic['caption'] = $(this).find('.caption_input').val()
            var tp = $(this).find('select').val()
            if (tp == 2) {
                $(this).find('li').each(function () {
                    var option_dic = {'id': undefined, 'name': undefined, 'score': undefined}

                    option_dic['id'] = $(this).attr('id')
                    option_dic['name'] = $(this).find('#id_name').val()
                    option_dic['score'] = $(this).find('#id_score').val()
                    dic['options'].push(option_dic)
                })
            }
            dic['tp'] = tp
            plist.push(dic)
        });
        console.log(plist)
        $.ajax({
            url: '/edit/{{ pid }}/',
            type: 'POST',
            data: {
                "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
                'pid':{{ pid }},
                'plist': JSON.stringify(plist),
            },
            success: function (data) {
                JSON.parse(data)
                if (data.msg) {
                    alert(data.msg)
                }
                else {
                    alert('保存成功')
                    location.href = '/index/'
                }
            }


        })


    })


</script>


</body>
</html>
edit.html(js代碼是重點!)

 

填寫問卷

#用於限制輸入長度的函數
def func(val):
    if len(val) < 15:
        raise ValidationError('你過短了')



def score(request, class_id, qn_id):
    """
    :param request:
    :param class_id: 班級ID
    :param qn_id: 問卷ID
    :return:
    """
    # student_id = request.session['student_info']['id']
    student_id = 1
    # 1. 當前登陸用戶是不是要評論的班級的學生
    ct1 = models.Student.objects.filter(id=student_id, cls_id=class_id).first()
    if not ct1:
        return HttpResponse('你只能評論本身班級的問卷,是否是想轉班?')

    # 2. 你是否已經提交過當前問卷答案
    ct2 = models.Answer.objects.filter(stu_id=student_id, question__naire_id=qn_id).first()
    if ct2:
        return HttpResponse('你已經參與過調查,沒法再次進行')

    # 3. 展現當前問卷下的全部問題
    # question_list = models.Question.objects.filter(naire_id=qn_id)

    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets


    field_dict = {}
    for que in question_list:
        print(que.caption)
        if que.tp == 1:
            field_dict['val_%s' % que.id] = fields.ChoiceField(
                label=que.caption,
                error_messages={'required':'必填'},
                widget=widgets.RadioSelect,
                choices=[(i, i) for i in range(1, 11)]
            )
        elif que.tp == 2:
            field_dict['option_id_%s' % que.id] = fields.ChoiceField(
                label=que.caption,
                widget=widgets.RadioSelect,
                choices=models.Option.objects.filter(
                    qs_id=que.id).values_list('id', 'name'))
        else:
            from django.core.exceptions import ValidationError
            from django.core.validators import RegexValidator
            # field_dict['x_%s' % que.id] = fields.CharField(
            #     label=que.caption, widget=widgets.Textarea,validators=[RegexValidator(regex=""),])
            field_dict['content_%s' % que.id] = fields.CharField(
                label=que.caption, widget=widgets.Textarea, validators=[func, ])
    #
    MyTestForm = type("MyTestForm", (Form,), field_dict)

    if request.method == 'GET':
        form = MyTestForm()
        return render(request, 'score.html', {'question_list': question_list, 'form': form})
    else:
        # 15字驗證
        # 不容許爲空
        form = MyTestForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            # {'x_2': '3', 'x_9': 'sdfasdfasdfasdfasdfasdfasdf', 'x_10': '13'}
            objs = []
            for key,v in form.cleaned_data.items():
                k,qid = key.rsplit('_',1)
                answer_dict = {'stu_id':student_id,'question_id':qid,k:v}
                objs.append(models.Answer(**answer_dict))
            models.Answer.objects.bulk_create(objs)
            return HttpResponse('感謝您的參與!!!')

        return render(request, 'score.html', {'question_list': question_list, 'form': form})
Views.py中的score
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    <style>
        ul{
            list-style-type: none;
        }
        ul li{
            display: inline-block;
        }
    </style>
</head>
<body>
    <div>
        <form method="post" novalidate>
            {% csrf_token %}
            {% for fd in form %}
                <div>
                    <p>{{ fd.label }} {{ fd.errors.0 }}</p>
                    {{ fd }}
                </div>
            {% endfor %}
            <input type="submit" value="提交">
        </form>
    </div>
</body>
</html>
score.html
相關文章
相關標籤/搜索