Django框架实现在线考试系统的示例代码

1.Django的简介

Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下:

层次 职责
模型(Model),即数据存取层 模型(Model),即数据存取层
模板(Template),即表现层 处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
视图(View),即业务逻辑层 存取模型及调取恰当模板的相关逻辑。模型与模板的桥梁。

Django里重要的概念有:

  • 路由映射
  • 视图函数
  • 模板渲染
  • Django自带的ORM操作(对象关系映射)

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-validators

AUTH_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 = True

USE_L10N = True

USE_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'),
]

需要注意的地方有:

  • NSTALLED_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_name
  def __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_name
  def __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_name
  def __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_name
  def __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="external nofollow" rel="external nofollow" 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="external nofollow" 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/" rel="external nofollow" ><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" rel="external nofollow" >管理员</a>
    </li>

    <li style="position: fixed;right: 70px; font-size: 40px;color: #9fcdff">{{ student.name }}{{ message }}</li>
    <a href="/logout/" rel="external nofollow" ><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" rel="external nofollow" >个人信息</a>
  </li>
  <li class="nav-item">
   <a class="nav-link" data-toggle="pill" href="#menu1" rel="external nofollow" >考试信息</a>
  </li>
  <li class="nav-item">
   <a class="nav-link" data-toggle="pill" href="#menu2" rel="external nofollow" >成绩查询</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 }}" rel="external nofollow" rel="external nofollow" >
       <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">&times;</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">&times;</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 views

urlpatterns = [
  #管理员登陆
  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等模板语句渲染


   <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 }}" rel="external nofollow" rel="external nofollow" >
       <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="external nofollow" rel="external nofollow" 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="external nofollow" rel="stylesheet" type="text/css" />

  <link href="../static/css/test.css" rel="external nofollow" 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>

效果是这样的:

自动阅卷就简单了:

  1. 学生提交自己的作答给服务器(同时发送自己的学号和考试科目)
  2. 服务器根据考试科目找到该试卷,并逐个比较学生作答和答案是否一致,若一致,则得到该题的分数,并累加学生成绩
  3. 将学生的学号、该科成绩、科目名称作为一条记录插入到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#初始化一个成绩为0
    for 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可视化数据
教师查看学生成绩,可以统计各个分数段的人数

我的思路:

  1. 教师查看学生成绩,点击查看成绩按钮后,发送该科科目名称给后台后台
  2. 视图函数接收科目名,从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框架实现在线考试系统的示例代码的文章就介绍到这了,更多相关Django 在线考试系统内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Django实现学生管理系统

    Django学习笔记-学生管理系统(Django实现)笔记中仅实现了对数据的全部查询. 下面实现新增.删除.修改,代码如下. 下面的代码没有对输入框内容进行限制,如果输入不符合规则的内容,会出现错误. 本篇更新完毕后Django更新暂停一段,由于工作岗位是测试工程师,后面将重点关注测试相关内容. views.py from django.shortcuts import render,reverse from stusys import models from django.http impor

  • python django集成cas验证系统

    加入cas的好处 cas是什么东西就不多说了,简而言之就是单点登陆系统,一处登陆,全网有权限的系统均可以访问. 一次登陆,多个系统互通 cas一般均放置在内网,加入cas验证则必须要求用户走vpn访问,提高安全性; cas可和域控等系统结合,密码定时过期; 基本认证统一走cas控制,减去开帐号等麻烦事; django 如何使用cas验证 django 的好处就是支持的包多,网上已经有大神做好的相关的app,直接下载.安装就可以了. 我们要做的就是下载.解压拷贝,略微配置下就可以跑了. 至于安装也

  • python3.6+django2.0开发一套学员管理系统

    1.在pycharm中新建project demo1 添加app01 点击create按钮完成新建 2.在demo项目目录下新建目录static,并在settings.py中追加代码: STATICFILES_DIRS=(os.path.join(BASE_DIR, 'static'),) 3.在setting.py中添加模板路径: TEMPLATES = [ { 'BACKEND': '...', 'DIRS': [os.path.join(BASE_DIR, 'templates'),],

  • Django admin实现图书管理系统菜鸟级教程完整实例

    Django 有着强大而又及其易用的admin后台,在这里,你可以轻松实现复杂代码实现的功能,如搜索,筛选,分页,题目可编辑,多选框. 简单到,一行代码就可以实现一个功能,而且模块之间耦合得相当完美. 不信,一起来看看吧!?用Django实现管理书籍的系统,并能在前台界面对书籍进行增删查改,筛选,分页,以及批量查询修改功能. 准备工作 #准备好你的数据库模型思维导图 0.新建一个Django项目,起名为books,并且同时新建一个应用book11 1.首先要设置models模块,根据思维导图,我

  • django的登录注册系统的示例代码

    摘要 django框架本身自带有登录注册,也可以自己写登录注册,下面将介绍这这2种方式实登录注册 一.自己写登录注册登出 1.注册regist 注册采用的是form表单,提交到数据库,在登录的时候,查询数据看,看用户有没有注册,如果用户没有注册,则返回注册页面注册 (1)models.py文件里创建相关的字段: 用户名字/用户密码/cookies携带的ticket from django.db import models # Create your models here. class User

  • 基于Django用户认证系统详解

    一. 认证系统概要 create_user 创建用户 authenticate 验证登录 login 记住用户的登录状态 logout 退出登录 is_authenticated 判断用户是否登录 login_required 判断用户是否登录的装饰器 二. 创建用户和验证登录 当用户注册的时候用create_user(username,password,email)默认情况下is_active=True,is_staff=False,is_superuser=False. 底层将passwor

  • django 捕获异常和日志系统过程详解

    这一块的内容很少, 异常使用try except即可, 日志只需要几行配置. 使用装饰器捕获方法内的所有异常 我使用装饰器来整个包裹一个方法, 捕获方法中的所有异常信息.并将其转为json返回客户端. import functools def catch_exception(func, code=500, *args, **kwargs): ''' :param func: :return: ''' @functools.wraps(func, *args, **kwargs) def nefe

  • Django框架实现在线考试系统的示例代码

    1.Django的简介 Django是一个基于MVC构造的框架.但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model).模板(Template)和视图(Views),称为 MTV模式.它们各自的职责如下: 层次 职责 模型(Model),即数据存取层 模型(Model),即数据存取层 模板(Template),即表现层 处理与表现相关的决定: 如何在页面或其他类型文档中进行显示. 视图(View),即业务逻辑层 存取模型及调取恰当模板的相

  • 基于Qt实现驾校科目考试系统的示例代码

    目录 1.设置登录界面 2.登录功能实现 2.1验证邮箱地址 2.2账号密码登录 2.3密码隐藏 3.考试界面开发 3.1考试用时 3.2题目布局 3.3按钮布局 3.4提交分数 3.5窗口交互 4.发布项目 4.1更改编译路径 4.2设置图标 4.3通过dos进行项目打包 1.设置登录界面 LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this

  • Django框架基础认证模块auth应用示例

    目录 1. auth介绍 2. autho常用操作 2.1 创建用户 2.2 验证用户 2.3 验证用户是否登录 2.4 已验证的用户想附加到当前会话 2.5 快捷增加登录校验装饰器 2.6 退出登录 2.7 检查密码 2.8 修改密码 2.9. 示例:利用auth模块搭建登录才能访问和有退出功能的页面 2.10 User对象的is_staff和is_active 3. 扩展默认的auth_user表 3.1 方案一: 一对一扩展 3.2 方案二: 继承AbstractUser类扩展 1. au

  • php实现在线考试系统【附源码】

    说明:本篇文章是为了记录下学习开发思路,程序不具备商业价值,明白开发思路,商用需二次升级! 效果图如下: 题库首页展示 试题在线测试 分数统计 通过该小项目目的是练习PHP基础知识,通过对数组操作实现考题信息存储加载,引入模板文件,实现考题数据的调用布局. 1.由于小项目未使用数据库,考题以数组的形式存储在PHP文件中,部分代码如下: <?php//考试题库二return [ //题库标题 'title' => 'PHP基础语法考试题(二)', //答题时限(秒数) 'timeout' =&g

  • Python django框架开发发布会签到系统(web开发)

    引言 最近学习了虫师的发布会签到系统demo,结合自己所学django知识,对demo重新塑造了一下.也是为了练练手,巩固知识.现在就分享一下成果~ Django工作流 学习django web开发,先来简单了解一下django的工作机制,请看下图: 简单说明: 用户通过浏览器访问:http://127.0.0.1:8000/index,首先运行的是urlpatterns程序,通过url路由找到对应的视图函数views.py,视图函数处理所有逻辑和数据,并且将用户要的数据经过函数处理后通过ind

  • Java项目实战之在线考试系统的实现(系统介绍)

    1.本系统和现在有的考试系统有以下几种优势: a.和现在有的系统比较起来,本系统有科目.章节.老师.学生.班级等信息的管理,还有批阅试卷查看已批阅试卷等.传统的考试系统划分并不细,业务功能简单. b.和学校的考试系统还有外面的考试系统比较起来,本系统是B/S结构,学校的考试系统一般为C/S结构,性能方面不如B/S结构,并且C/S接口需要安装客户端,客户端压力很大,我的系统只需要电脑具有浏览器,在同一局域网就可以进行考试. c.从架构方面来讲,我们的系统为分布式架构,传统的考试系统没有我们的架构合

  • Java实现在线考试系统与设计(学生功能)

    学生模块功能比较少,就是进行考试和查看自己成绩两个大的功能. 学生进行考试的功能比较复杂(首先做了校验,不在考试时间范围内,不能进行考试) 考试试题是数据库根据发布考试时的条件随机产生的一套试题.因为每次考试题型题量都是不同的,因此我们继续采用JSON的格式去保存数据,当状态为1:表示正在考试:状态为2:表示已经考试结束:状态为3:表示老师已经阅完试卷 (1)当考试考试的时候,会给考上随机产生一套试题,并存储到数据库中,如果考试中电脑突然坏了可以保证重新打开还是之前的试题 (2)考试时间结束会自

  • Java Online Exam在线考试系统的实现

    一.项目简述 本系统主要实现的功能有: 学生以及老师的注册登录,在线考试,错题查询,学生管理,问题管理,错题管理,错题查询,分数查询,试卷管 理,人工组卷.自动组卷,教师,班级,统计等等管理功能. 二.项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts 都支持) 项目技术: VUE+Springboot+ SpringMVC + MyBatis + ThymeLeaf + Jav

  • WPF+ASP.NET SignalR实现简易在线聊天功能的示例代码

    目录 涉及知识点 什么是ASP.NET SignalR 在线聊天整体架构 ASP.NET SignalR在线聊天服务端 1. 创建ASP.NET Web API项目 2. 创建消息通知中心Hub 3. 注册服务和路由 4. ASP.NET SignalR中心对象生存周期 SignalR客户端 1. 安装SignalR客户端依赖库 2. 客户端消息接收发送 运行示例 在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计.有没

  • 使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    本项目主要实现对汽车维修厂的信息化管理功能,主要包含三个角色:管理员,维修师傅,客户.实现的主要功能包含用户管理.配置管理.汽车管理.故障管理.供应商管理.配件管理.维修订单管理.统计信息.公告管理.个人信息管理.主要业务流程:用户在系统内发起汽车维修申请定单,管理员根据情况将定单分配给维修师傅,维修师傅接受任务后开始维修,并根据情况申请配件,处理完成后由管理员生成最终支付订单结算费用,客户进入系统进行费用支付,并可以查看自己相应的维修记录和费用信息等等. 技术架构: 后台开发:SSM框架 前端

随机推荐