遇見Django框架之在線考試系統 1.Django的簡介 2.項目的設計思路 3.搭建你的開發環境 4.分模塊詳細設計 5.總結
1.Django的簡介
Django是一個基于MVC構造的框架。但是在Django中,控制器接受用戶輸入的部分由框架自行處理,所以 Django 里更關注的是模型(Model)、模板(Template)和視圖(Views),稱為 MTV模式。它們各自的職責如下:
層次職責 模型(Model),即數據存取層 模型(Model),即數據存取層 模板(Template),即表現層 處理與表現相關的決定: 如何在頁面或其他類型文檔中進行顯示。 視圖(View),即業務邏輯層 存取模型及調取恰當模板的相關邏輯。模型與模板的橋梁。
Django里重要的概念有:
路由映射 視圖函數 模板渲染 Django自帶的ORM操作(對象關系映射)
需要學習Django基礎的同學可以瀏覽以下網站(非常有用): Django中文手冊 自強學堂 Django基礎教程 django中文網
2.項目的設計思路
1.在線考試系統需求如下: (1)系統登錄:驗證登錄用戶的身份,根據用戶身份進入不同的頁面。 (2)學生管理:供管理員使用,用于維護學生基本信息。 (3)老師管理:供管理員使用,用于維護教師的基本信息。 (4)試題管理:供教師管理,用于維護題庫。 (5)組卷:供教師使用,教師可以根據考試科目,從題庫中選擇一些符合條件的試題,形成一份試卷。為了方便教師組卷,應提供方便的查詢功能,使教師能查詢不同要求的試題。 (6)在線考試:供學生使用,根據學生的班級和登錄時間顯示應考科目的試卷內容。試卷完成提交或考試時間到,不再允許學生修改試卷;實現自動評閱,記錄學生的考試成績,并將評閱結果提供給學生。 (7)成績統計:供教師使用,按照科目、班級等統計學生的考試成績。 (8)成績查詢:供教師和學生使用,提供不同查詢方式,使教師和學生可以按需查詢考試成績。
2.設計思路 (1)確定角色 由需求分析看出,系統有三個基本角色,學生、教師、管理員。
(2)數據庫表的設計 因此,我們至少需要如下幾個表:
學生表 student 教師表 teacher 題庫表 question(為了方便,題庫中都為單項選擇題) 試卷表 paper 學生成績表 grade
設計完表,我們還需要確定表間的關系,是1對1(1:1),1對多(1:n),還是多對多(n:m) ,這很重要,因為后面我們在models.py中創建表時,需要指出表間關系。 顯然
學生表和成績表,1個學生可參加多門考試,會有多個成績,學生表和成績表為1:n 教師表和試卷表,1個教師會發布多套試卷,但1套試卷只能由1位教師發布,教師表和試卷表為1:n 試卷表和題庫表,1套試卷里包含多道題,題庫里的每道題也可出現在多個試卷中,故試卷表和題庫表為n:m
表的詳細設計如下:(使用MindMaster繪制,有點丑,請忽略,重點寫下自己的思考和思路)
3.搭建你的開發環境
IDE使用PyCharm(profession版的) python 3.7, Django 2.1.0 數據庫為關系數據庫mysql 5.6
為了更快的下載python模塊,需要切換鏡像源,我使用阿里云的鏡像(還有很多鏡像源),方法如下: 在 C:\Users\XXX(你的賬戶) 下建立 pip文件夾,在pip下建立 pip.ini文件,輸入以下代碼:
[global] index-url = http://mirrors.aliyun.com/pypi/simple/ [install] trusted-host=mirrors.aliyun.com
安裝所需模塊
Django的安裝: pip install django==2.1.0(請指定版本號,最新的Django需要數據庫mysql5.6以上),你可以使用pip list來查看版本,使用 pip uninstall django 來卸載django模塊 安裝mysql數據庫驅動 pip install pymysql 配置好后建立項目
(1) 在PyCharm中建立Django項目 圖1 建立項目 此處沒有使用虛擬環境,你也可以選擇 “New environment using”選項來創建一個虛擬環境(可以避免多個項目使用不同模塊的版本時發生沖突)
(2)創建app Tools->Run manage.py task
在控制臺輸入 startapp student,創建一個student app, 之后需要將student app配置在項目的settings.py中,由于我的前臺需要用到css、BootStrap、一些圖片等文件,所以我在項目下建立static文件夾,并將其路徑配置在settings.py文件中。整體目錄如下: (3)settings.py文件的配置 配置settings.py文件配置如下,請看注釋
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','student',#將建立的app名稱加入Installed_APPs中
]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware',# 'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]ROOT_URLCONF = 'onlineExam.urls'TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},
]WSGI_APPLICATION = 'onlineExam.wsgi.application'# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases#配置mysql數據庫
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'exam',#使用數據庫的名稱'USER':'root',#用戶名'PASSWORD':'123456',#密碼'HOST':'127.0.0.1',#地址'PORT':'3306'#端口號}
}# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validatorsAUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},
]# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/#修改語言為中文
LANGUAGE_CODE = 'zh-hans'#修改時區為shanghai
TIME_ZONE = 'Asia/Shanghai'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = True# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/#添加static文件夾
STATIC_URL = '/static/'
STATICFILES_DIRS=[os.path.join(BASE_DIR,'static'),
]
需要注意的地方有:
INSTALLED_APPS 添加了新建的student app DATABASES 配置你的數據庫參數 MIDDLEWARE 注釋掉了 # 'django.middleware.csrf.CsrfViewMiddleware’這一行 STATICFILES_DIRS 添加新建的static文件夾
(4)在__init___.py文件添加mysql的驅動模塊
import pymysql
pymysql.install_as_MySQLdb()
4.分模塊詳細設計
(1)建表 在student下的models.py中建表
from django.db import models# Create your models here.# 為性別,學院 指定備選字段
SEX=(('男','男'),('女','女'),
)
DEPT=(('計算機與通信學院','計算機與通信學院'),('電氣與自動化學院','電氣與自動化學院'),('外國語學院','外國語學院'),('理學院','理學院'),
)class Student(models.Model):id=models.CharField('學號',max_length=20,primary_key=True)name=models.CharField('姓名',max_length=20)sex=models.CharField('性別',max_length=4,choices=SEX,default='男')dept=models.CharField('學院',max_length=20,choices=DEPT,default=None)major=models.CharField('專業',max_length=20,default=None)password=models.CharField('密碼',max_length=20,default='111')email=models.EmailField('郵箱',default=None)birth=models.DateField('出生日期')class Meta:db_table='student'verbose_name='學生'verbose_name_plural=verbose_namedef __str__(self):return self.id;class Teacher(models.Model):id=models.CharField("教工號",max_length=20,primary_key=True)name=models.CharField('姓名',max_length=20)sex=models.CharField('性別',max_length=4,choices=SEX,default='男')dept=models.CharField('學院',max_length=20,choices=DEPT,default=None)email=models.EmailField('郵箱',default=None)password=models.CharField('密碼',max_length=20,default='000000')birth=models.DateField('出生日期')class Meta:db_table='teacher'verbose_name='教師'verbose_name_plural=verbose_namedef __str__(self):return self.name;class Question(models.Model):ANSWER=(('A','A'),('B','B'),('C','C'),('D','D'),)LEVEL={('1','easy'),('2','general'),('3','difficult'),}id = models.AutoField(primary_key=True)subject = models.CharField('科目', max_length=20)title = models.TextField('題目')optionA=models.CharField('A選項',max_length=30)optionB=models.CharField('B選項',max_length=30)optionC=models.CharField('C選項',max_length=30)optionD=models.CharField('D選項',max_length=30)answer=models.CharField('答案',max_length=10,choices=ANSWER)level=models.CharField('等級',max_length=10,choices=LEVEL)score=models.IntegerField('分數',default=1)class Meta:db_table='question'verbose_name='單項選擇題庫'verbose_name_plural=verbose_namedef __str__(self):return '<%s:%s>'%(self.subject,self.title);class Paper(models.Model):#題號pid 和題庫為多對多的關系pid=models.ManyToManyField(Question)#多對多tid=models.ForeignKey(Teacher,on_delete=models.CASCADE)#添加外鍵subject=models.CharField('科目',max_length=20,default='')major=models.CharField('考卷適用專業',max_length=20)examtime=models.DateTimeField()class Meta:db_table='paper'verbose_name='試卷'verbose_name_plural=verbose_namedef __str__(self):return self.major;class Grade(models.Model):sid=models.ForeignKey(Student,on_delete=models.CASCADE,default='')#添加外鍵subject=models.CharField('科目',max_length=20,default='')grade=models.IntegerField()def __str__(self):return '<%s:%s>'%(self.sid,self.grade);class Meta:db_table='grade'verbose_name='成績'verbose_name_plural=verbose_name
(2)將模型映射到mysql數據庫中,很簡單,打開 Run manage.py Task,輸入遷移命令 先輸入makemigrate命令,作用是生成sql文件(create table student(id,sex,…) ),執行后可在student-> migrations下看到執行結果 再輸入migrate命令,執行makemigrate生成的sql語句,表就建好了,你可以使用navicat或workBench等工具看到Django為我們建好的表
(2)創建管理員 繼續輸入createsuperuser命令創建管理員,以便登陸后臺 (3)創建模板 在templates中建立index.html模板,作為考試系統首頁.(可去官網下載BootStrap、JQuery) 在頭文件里引入時注意順序,jquery須在bootstrap.min.js之前引入
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link href="../static/bootstrap-4.3.1-dist/css/bootstrap.min.css" rel="stylesheet"><!-- 必須在引入bootstarp.js之前引入 --><script src="../static/jquery-3.3.1.min.js"></script><script src="../static/bootstrap-4.3.1-dist/js/bootstrap.min.js"></script><link href="../static/css/index.css" rel="stylesheet"><title>在線考試系統</title></head>
<body><nav class="navbar navbar-expand-sm bg-light navbar-light "><ul class="navbar-nav"><li class="nav-item"><a class="nav-link" href="/toIndex/"><h3>在線考試系統 首頁</h3></a></li><li><button data-target="#stuModal" data-toggle="modal" class="btn btn-primary">學生登陸</button></li><li><button data-target="#teaModal" data-toggle="modal" class="btn btn-primary">教師登陸</button></li><li class="nav-item"><a class="nav-link" href="/admin">管理員</a></li><li style="position: fixed;right: 70px; font-size: 40px;color: #9fcdff">{{ student.name }}{{ message }}</li><a href="/logout/"><li style="position: fixed;right: 20px; font-size: 20px;top:22px;color:#cc1313">退出</li></a></ul>
</nav><div class="container"><br><!-- Nav pills --><ul class="nav nav-pills" role="tablist"><li class="nav-item"><a class="nav-link active" data-toggle="pill" href="#home">個人信息</a></li><li class="nav-item"><a class="nav-link" data-toggle="pill" href="#menu1">考試信息</a></li><li class="nav-item"><a class="nav-link" data-toggle="pill" href="#menu2">成績查詢</a></li></ul><!-- Tab panes --><div class="tab-content"><div id="home" class="container tab-pane active"><br><h3>個人信息</h3><table class="table"><thead><tr><th>屬性</th><th>信息</th></tr></thead><tbody><tr><td>學號</td><td>{{ student.id }}</td></tr><tr class="table-primary"><td>姓名</td><td>{{ student.name }}</td></tr><tr class="table-success"><td>性別</td><td>{{ student.sex }}</td></tr><tr class="table-danger"><td>學院</td><td>{{ student.dept }}</td></tr><tr class="table-success"><td>專業</td><td>{{ student.major }}</td></tr><tr class="table-warning"><td>郵箱地址</td><td>{{ student.email }}</td></tr><tr class="table-active"><td>出生日期</td><td>{{ student.birth }}</td></tr></tbody></table></div><div id="menu1" class="container tab-pane fade"><br><h3>考試信息</h3><p></p><table class="table"><thead><tr><th>學號</th><th>姓名</th><th>考試科目</th><th>考試時間</th><th>操作</th></tr></thead><tbody>{# 遍歷字典 paper #}{% for paper1 in paper %}<tr class="table-info"><td>{{ student.id }}</td><td>{{ student.name }}</td><td>{{ paper1.subject }}{{ paper2.subject }}</td><td>{{ paper1.examtime }} {{ paper2.examtime }}</td><td><a href="/startExam/?sid={{ student.id }}&subject={{ paper1.subject }}"><button class="btn btn-primary" id="toExam+{{ paper1.subject }}">開始考試</button></a></td></tr>{% endfor %}</tbody></table></div><div id="menu2" class="container tab-pane fade"><br><h3>考試成績</h3><p></p><table class="table"><thead><tr><th>姓名</th><th>科目</th><th>成績</th></tr></thead><tbody>{% for grade1 in grade %}<tr class="table-primary"><td>{{ student.name }}</td><td>{{ grade1.subject }}</td><td>{{ grade1.grade }}</td></tr>{% endfor %}</tbody></table></div></div>
</div>{#學生登錄的模態對話框#}
<div class="modal fade" tabindex="-1" role="dialog" id="stuModal"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title">學生登陸</h4></div><form class="form-horizontal" action="/studentLogin/" method="post"><div class="modal-body"><div class="form-group"><label class="col-sm-3 control-label">學生學號</label><div class="col-sm-9"><input type="text" class="form-control" name="id" placeholder="輸入學號"></div></div><div class="form-group"><label for="addr" class="col-sm-3 control-label">密碼</label><div class="col-sm-9"><!--<textarea id="addr" class="form-control" rows="3"></textarea>--><input type="password" class="form-control" name="password" placeholder="輸入密碼"></div></div></div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">取消</button><button type="submit" class="btn btn-primary">登陸</button></div></form></div><!-- /.modal-content --></div><!-- /.modal-dialog -->
</div>{#老師登錄的模態對話框#}
<div class="modal fade" tabindex="-1" role="dialog" id="teaModal"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title">教師登陸</h4></div><form class="form-horizontal" action="/teacherLogin/" method="post"><div class="modal-body"><div class="form-group"><label for="inputEmail3" class="col-sm-3 control-label">教師工號</label><div class="col-sm-9"><input type="text" class="form-control" name="id" placeholder="輸入學號"></div></div><div class="form-group"><label for="addr" class="col-sm-3 control-label">密碼</label><div class="col-sm-9"><!--<textarea id="addr" class="form-control" rows="3"></textarea>--><input type="password" name="password" placeholder="輸入密碼" class="form-control"></div></div></div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">取消</button><button type="submit" class="btn btn-primary">登陸</button></div></form></div><!-- /.modal-content --></div><!-- /.modal-dialog -->
</div></body><script>$("#toExam+{{ paper1.subject }}").click(function () {});
</script>
</html>
Django使用{{ }}來使用后臺傳來的數據 (4)創建視圖函數 在student->views.py中創建進入首頁的視圖函數index()
from django.shortcuts import render,redirect
from student import models
from django.http import HttpResponse
from django.contrib.auth import logout
# Create your views here.
def index(request):return render(request,'index.html')
將視圖函數配置在路由中,打開項目的urls.py文件
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from student import viewsurlpatterns = [#管理員登陸path('admin/', admin.site.urls),#默認訪問首頁url(r'^$',views.index),
]
r表示使用正則表達式解析url地址,^表示開始,$表示結束,views.index表示調用視圖函數index (5)啟動服務器(可以看到效果了) 兩種方式啟動服務器:執行runserver命令,或點擊綠色小圖標 點擊網址,默認8000端口,成功后如下圖
我們還需要定制自己的后臺,在student->admin.py中注冊各模塊
from django.contrib import admin
from .models import Student,Teacher,Paper,Question,Grade
# Register your models here.
# 修改名稱
admin.site.site_header='在線考試系統后臺'
admin.site.site_title='在線考試系統'@admin.register(Student)
class StudentAdmin(admin.ModelAdmin):list_display = ('id','name','sex','dept','major','password','email','birth')# 要顯示哪些信息list_display_links = ('id','name')#點擊哪些信息可以進入編輯頁面search_fields = ['name','dept','major','birth'] #指定要搜索的字段,將會出現一個搜索框讓管理員搜索關鍵詞list_filter =['name','dept','major','birth']#指定列表過濾器,右邊將會出現一個快捷的過濾選項
對其他4個model注冊后臺
@admin.register(Teacher)
class TeacherAdmin(admin.ModelAdmin):list_display = ('id', 'name', 'sex', 'dept', 'password', 'email', 'birth')list_display_links = ('id', 'name')search_fields = ['name', 'dept', 'birth']list_filter = ['name','dept']@admin.register(Question)
class QuestionAdmin(admin.ModelAdmin):list_display = ('id','subject','title','optionA','optionB','optionC','optionD','answer','level','score')
刷新,點擊首頁管理員超鏈接,進入后臺,使用前邊創建的superuser賬戶和密碼登陸 進入后臺 使用后臺添加學生信息 (6)實現學生的登陸 這里需要用到Django內置的ORM模塊,不在贅述,需要的同學看前邊網站入門。
在views.py中創建studentLogin函數 學生登陸的form表單將學生輸入的學號(id),密碼(password)通過post方式提交給服務器,所以視圖函數先接受表單參數,判斷用戶名和密碼與數據庫是否一致,若一致,則登陸成功。 登陸成功后,我需要發送至少三條信息給index.html, (1)該學生的基本信息 (2)該學生考試信息,可通過該學生的專業名稱在試卷表中查到有哪些要進行的考試 (3)該學生的考試成績信息,可通過學生的學號在paper表中查詢 代碼如下:
def studentLogin(request):if request.method=='POST':# 獲取表單信息stuId=request.POST.get('id')password=request.POST.get('password')print("id",stuId,"password",password)# 通過學號獲取該學生實體student=models.Student.objects.get(id=stuId)print(student)if password==student.password: #登錄成功#查詢考試信息paper=models.Paper.objects.filter(major=student.major)#查詢成績信息grade=models.Grade.objects.filter(sid=student.id)# 渲染index模板return render(request,'index.html',{'student':student,'paper':paper,'grade':grade})else:return render(request,'index.html',{'message':'密碼不正確'})
(7)模板的渲染(數據的顯示) 登陸成功后,發送三個字典數據給index,index模板使用{{ }}、for等模板語句渲染
<div class="tab-content"><div id="home" class="container tab-pane active"><br><h3>個人信息</h3><table class="table"><thead><tr><th>屬性</th><th>信息</th></tr></thead><tbody><tr><td>學號</td><td>{{ student.id }}</td></tr><tr class="table-primary"><td>姓名</td><td>{{ student.name }}</td></tr><tr class="table-success"><td>性別</td><td>{{ student.sex }}</td></tr><tr class="table-danger"><td>學院</td><td>{{ student.dept }}</td></tr><tr class="table-success"><td>專業</td><td>{{ student.major }}</td></tr><tr class="table-warning"><td>郵箱地址</td><td>{{ student.email }}</td></tr><tr class="table-active"><td>出生日期</td><td>{{ student.birth }}</td></tr></tbody></table></div><div id="menu1" class="container tab-pane fade"><br><h3>考試信息</h3><p></p><table class="table"><thead><tr><th>學號</th><th>姓名</th><th>考試科目</th><th>考試時間</th><th>操作</th></tr></thead><tbody>{# 遍歷字典 paper #}{% for paper1 in paper %}<tr class="table-info"><td>{{ student.id }}</td><td>{{ student.name }}</td><td>{{ paper1.subject }}{{ paper2.subject }}</td><td>{{ paper1.examtime }} {{ paper2.examtime }}</td><td><a href="/startExam/?sid={{ student.id }}&subject={{ paper1.subject }}"><button class="btn btn-primary" id="toExam+{{ paper1.subject }}">開始考試</button></a></td></tr>{% endfor %}</tbody></table></div><div id="menu2" class="container tab-pane fade"><br><h3>考試成績</h3><p></p><table class="table"><thead><tr><th>姓名</th><th>科目</th><th>成績</th></tr></thead><tbody>{% for grade1 in grade %}<tr class="table-primary"><td>{{ student.name }}</td><td>{{ grade1.subject }}</td><td>{{ grade1.grade }}</td></tr>{% endfor %}</tbody></table></div></div>
(8)教師登陸同上,學生在線考試和系統自動閱卷怎么實現呢?我是這樣做的
學生登陸成功后,點擊"開始考試"按鈕,按鈕將兩個請求信息發送到服務器,自己的學號和試卷的科目。 startExam視圖函數接收到學號和試卷的科目,找到試卷信息發送給另一模板(exam.html)渲染 因此,建立繼續建立exam.html模板和startExam視圖函數
def startExam(request):sid = request.GET.get('sid')subject1=request.GET.get('subject')#得到學生信息student=models.Student.objects.get(id=sid)#試卷信息paper=models.Paper.objects.filter(subject=subject1)# print('學號',sid,'考試科目',subject1)return render(request,'exam.html',{'student':student,'paper':paper,'subject':subject1})
exam模板如下:
<!DOCTYPE HTML>
<html lang="en">
<head><meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>在線答題考試系統</title><link href="../static/bootstrap-4.3.1-dist/css/bootstrap.min.css" rel="stylesheet"><!-- 必須在引入bootstarp.js之前引入 --><script src="../static/jquery-3.3.1.min.js"></script><script src="../static/bootstrap-4.3.1-dist/js/bootstrap.min.js"></script><script src="../static/js/jquery-1.11.3.min.js"></script><script src="../static/js/jquery.countdown.js"></script><!--時間js--><link href="../static/css/main.css" rel="stylesheet" type="text/css" /><link href="../static/css/test.css" rel="stylesheet" type="text/css" />
<style>
.hasBeenAnswer {background: #5d9cec;color:#fff;
}
</style></head>
<body><nav class="navbar navbar-expand-sm bg-light navbar-light "><ul class="navbar-nav"><li class="nav-item active"><a class="nav-link"><h3>在線考試系統</h3></a></li><li class="nav-item active"><a class="nav-link"><h3>當前科目:{{ subject }}</h3></a></li><li style="position: fixed;right: 70px; font-size: 30px;color: #9fcdff">{{ student.name }}</li></ul>
</nav>
<div class="main"><!--nr start--><div class="test_main"><div class="nr_left"><div class="test"><form action="/calGrade/" method="post"><input type="hidden" name="sid" value="{{ student.id }}"><input type="hidden" name="subject" value="{{ subject }}"><div class="test_title"><p class="test_time"><i class="icon iconfont"></i><b class="alt-1">01:40</b></p><font><input type="submit" name="tijiao" value="交卷"></font></div><div class="test_content"><div class="test_content_title"><h2>單選題</h2><p><span>共</span><i class="content_lit">10</i><span>題,</span><span>合計</span><i class="content_fs">10</i><span>分</span></p></div></div><div class="test_content_nr"><ul>{% for paper1 in paper %}{% for test in paper1.pid.all %}<li id="{{ forloop.counter }}"><div class="test_content_nr_tt"><i>{{ forloop.counter}}</i><span>({{ test.score }}分)</span><font>{{ test.title }}</font></div><div class="test_content_nr_main"><ul><li class="option"><input type="radio" class="radioOrCheck" name="{{ test.id }}"value="A"/><label>A.<p class="ue" style="display: inline;">{{ test.optionA }}</p></label></li><li class="option"><input type="radio" class="radioOrCheck" name="{{ test.id }}"value="B"/><label>B.<p class="ue" style="display: inline;">{{ test.optionB }}</p></label></li><li class="option"><input type="radio" class="radioOrCheck" name="{{ test.id }}"value="C"/><label>C.<p class="ue" style="display: inline;">{{ test.optionC }}</p></label></li><li class="option"><input type="radio" class="radioOrCheck" name="{{ test.id }}"value="D"/><label>D.<p class="ue" style="display: inline;">{{ test.optionD }}</p></label></li></ul></div></li>{% endfor %}{% endfor %}</ul></div></form></div></div></div><!--nr end--><div class="foot"></div>
</div></body>
</html>
效果是這樣的: 自動閱卷就簡單了:
學生提交自己的作答給服務器(同時發送自己的學號和考試科目) 服務器根據考試科目找到該試卷,并逐個比較學生作答和答案是否一致,若一致,則得到該題的分數,并累加學生成績 將學生的學號、該科成績、科目名稱作為一條記錄插入到grade表中,返回首頁
這里有個細節,試卷中會有很多選擇題,后臺一次會接收到多個提交答案,我是這樣處理的,讓每個單選題(有4個選項,使用同一name)的name屬性和該題在題庫表中的id 保持一致,這樣在獲取到題號后可以得到該題的答案,以便判斷是否作答正確,詳見exam.html。
計算成績的calGrade()視圖函數如下:
def calGrade(request):if request.method=='POST':# 得到學號和科目sid=request.POST.get('sid')subject1 = request.POST.get('subject')# 重新生成Student實例,Paper實例,Grade實例,名字和index中for的一致,可重復渲染student= models.Student.objects.get(id=sid)paper = models.Paper.objects.filter(major=student.major)grade = models.Grade.objects.filter(sid=student.id)# 計算該門考試的學生成績question= models.Paper.objects.filter(subject=subject1).values("pid").values('pid__id','pid__answer','pid__score')mygrade=0#初始化一個成績為0for p in question:qId=str(p['pid__id'])#int 轉 string,通過pid找到題號myans=request.POST.get(qId)#通過 qid 得到學生關于該題的作答# print(myans)okans=p['pid__answer']#得到正確答案# print(okans)if myans==okans:#判斷學生作答與正確答案是否一致mygrade+=p['pid__score']#若一致,得到該題的分數,累加mygrade變量#向Grade表中插入數據models.Grade.objects.create(sid_id=sid,subject=subject1,grade=mygrade)# print(mygrade)# 重新渲染index.html模板return render(request,'index.html',{'student':student,'paper':paper,'grade':grade})
(9)使用百度e-charts可視化數據 教師查看學生成績,可以統計各個分數段的人數 我的思路:
教師查看學生成績,點擊查看成績按鈕后,發送該科科目名稱給后臺 后臺視圖函數接收科目名,從grade表計算該科目各個分數段的人數,發送給前臺模板渲染,并可視化
視圖函數如下:
#教師查看成績
def showGrade(request):subject1=request.GET.get('subject')grade=models.Grade.objects.filter(subject=subject1)data1 = models.Grade.objects.filter(subject=subject1, grade__lt=60).count()data2 = models.Grade.objects.filter(subject=subject1, grade__gte=60, grade__lt=70).count()data3 = models.Grade.objects.filter(subject=subject1, grade__gte=70, grade__lt=80).count()data4 = models.Grade.objects.filter(subject=subject1, grade__gte=80, grade__lt=90).count()data5 = models.Grade.objects.filter(subject=subject1, grade__gte=90).count()data = {'data1': data1, 'data2': data2, 'data3': data3, 'data4': data4, 'data5': data5}return render(request,'showGrade.html',{'grade':grade,'data':data,'subject':subject1})
5.總結
第一次寫博客,感覺還不錯,希望和各位小伙伴討論。
總結
以上是生活随笔 為你收集整理的Django框架实现在线考试系统 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。