[Python + Django] Web在线考试管理系统设计及代码实现

     阅读:28

本文最终实现一个Web在线考试管理系统,可作为Python Web,Django的练手项目,也可以作为计算机毕设参考项目。

源码获取方式:【Django】pythonweb学生信息及考试管理系统毕业设计源码-Python文档类资源-CSDN下载

目录

系统功能需求分析

系统设计及实现思路

1、数据库设计

2、页面及功能设计

系统实现过程及源码

1 开发环境搭建及技术选型

2、Django项目创建及数据库连接配置

3、 数据库创建和连接配置

数据库创建

Django数据库连接配置

4、 功能模块详细开发

创建APP

注册APP

定义模型

定义视图函数

配置访问路由URL

静态资源准备及配置

模板创建

Django后台启用配置

运行服务器测试效果


系统功能需求分析

在线考试管理系统,主要包含如下几个功能模块:

1、用户登录及:实现简单的登录及验证

2**、个人信息展示**:展示考生个人信息

3、考试管理:展示可以考试的试卷,考试及自动计算考试成绩。

4、考试成绩管理:展示考试结果

5、后台基础数据管理:试卷,试题,考生等信息更新维护。

系统设计及实现思路

系统设计包括三部分:数据库设计,功能函数视图设计,前端页面设计

1、数据库设计

根据我们的的系统需求分析,我们预计需要如下几个数据表:

  • 学院表:Academy
  • 专业表:Major
  • 课程表:Course
  • 学生表:Student
  • 题库表:QuestionBank
  • 试卷表:TestPaper
  • 学生成绩表:Record

2、页面及功能设计

为了实现我们前面的功能模块我们设计如下几个功能页面:

1、登录页面:

其中需要登录,校验,登录后同时需要存储用户信息在Session中,以备登录后的页面使用。

2、首页(考试信息页):

页面需要显示当前用户可以参考的考试试卷信息,在此页面点击开始考试可以跳转到考试页面。

3、考试页面:

展示对应试卷的题目和选项信息,同时可以进行答题,交卷后可以自动计算考试分数并存入数据库。

4、成绩显示页面:

展示对应考试的考试结果

5、后台管理:

用于管理我们的专业,考生,试卷,题库等基础信息,为了快速实现系统我们将直接启用Django自带的Admin管理功能。

6、个人详情:

用于展示个人详情信息。

系统实现过程及源码

大致理清了我们需要实现的功能模块之后,我们开始撸代码

1 、开发环境搭建及技术选型

服务端:Python 3.8

Web框架:Django 3.2

数据库:MySQL mysql-8.0.13-winx64

开发工具IDE:Pycharm(社区版)

前端框架:Bootstrap 4

2、Django项目创建及数据库连接配置

1.在任意盘符文件夹下新建一个空白Pycharm项目文件夹比如:PycharmProjects

2.打开Pycharm,进入空白文件夹:PycharmProjects

3.通过Pycharm 的Windows 命令行输入界面输入创建Django项目的命令,创建一个新的项目: DjangoExam

django-admin startproject DjangoExam

3、 数据库创建和连接配置

Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。

Django 为这些数据库提供了统一的调用API。

我们可以根据自己业务需求选择不同的数据库。

MySQL 是 Web 应用中最常用的数据库。

本文采用MySQL。

此步骤将数据库设置连接到自己的MySQL数据库,并完成数据库的创建.

数据库创建

Django只能操作到数据表级别,不能操作到数据库级别,所以需要手工创建一个数据库:djangoexam

我们可以通过命令行创建一个数据库:

1.进入mysql安装文件夹的bin 子文件夹目录:

比如:D:Program Filesmysql-8.0.13-winx64in

2.连接数据库:

mysql -u root -p Enter password:******

3.连接登录成功后通过命令创建一个数据库:djangoexam

CREATE DATABASE IF NOT EXISTS djangoexam DEFAULT CHARSET utf8;

或者通过SQLlog工具创建一个数据库: djangoexam

Django数据库连接配置

Django使用MySQL需要mysql 驱动,如果你没安装 mysql 驱动,可以执行以下命令安装:

pip install pymysql

安装好之后,进入DjangoExam 项目下的DjangoExam 文件夹,打开setting.py 文件,找到DATABASES配置项,修改DATABSES配置项为如下内容:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',    # 数据库引擎
        'NAME': 'djangoexam', # 数据库名称
        'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1
        'PORT': 3306, # 端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '123456', # 数据库密码
    }
}

然后使用 pymysql 模块连接 mysql 数据库:

在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置:

import pymysql   
pymysql.install_as_MySQLdb()

至此,我们创建了一个Django项目DjangoExam用于我们后续的在线考试管理系统开发的程序编写。

同时为此项目创建了一个MySQL数据库:djangoexam用于我们程序开发过程中的数据存放和处理。

4、 功能模块详细开发

一个Django项目框架搭建起来后,我们所有对系统的前后台所有的程序开发都可以在这个项目中进行了,一个典型的Django项目模块功能的开发包括如下几个步骤:

  • 创建app
  • 注册app
  • 定义模型
  • 定义视图函数
  • 配置访问路由URL
  • 静态资源准备及配置
  • 前端模板开发
  • 测试及运行

创建APP

在Django中的一个app代表一个功能模块,Django 规定,如果要使用模型,必须要创建一个 app。

本来一般实际开发中方便管理一个功能模块需要单独新建一个app,我们为了快速开发,所有的功能和模型都在一个app中进行管理。

在命令行中输入python manage.py startapp exam指令,创建名为exam的app:

python manage.py startapp exam

注册APP

在 DjangoExam文件夹目录下的settings.py 中找到INSTALLED_APPS配置项,将新创建的exam添加到项目的app列表,如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'exam', #添加此项
]

定义模型

我们之前创建了一个空白的数据库djangoexam,这一步我们通过Django的模型来完成数据库表的创建.

因为Django对模型和目标数据库之间有自身的映射规则,如果自己在数据库中创建数据表,可能不一定符合Django的建表规则,从而导致模型和目标数据库无法建立通信联系。

所以最好我们在Django项目中还是通过Django模型来创建对应数据库表

一个表对应一个模型,本步骤按照我们前面数据库设计需要设计7个模型:

打开exam/models.py文件,输入如下代码:

from django.db import models

# 学院表
class Academy(models.Model):
    id = models.AutoField('序号',primary_key=True)
    name = models.CharField('学院',max_length=20)

    # 修改显示的表的名字
    class Meta:
        verbose_name = '学院'
        verbose_name_plural = '学院'

    def __str__(self):
        return self.name

# 专业表
class Major(models.Model):
    id = models.AutoField('序号',primary_key=True)
    academy = models.ForeignKey(Academy,on_delete=models.CASCADE,verbose_name='学院')
    major = models.CharField('专业',max_length=30)

    # 修改显示的表的名字
    class Meta:
        verbose_name = '专业'
        verbose_name_plural = '专业'
    def __str__(self):
        return self.major

# 课程表
class Course(models.Model):
    id = models.AutoField('序号',primary_key=True)
    course_id = models.CharField('课程号',max_length=10)
    course_name = models.CharField('课程名称',max_length=30)

    class Meta:
        verbose_name = '课程'
        verbose_name_plural = '课程'

    def __str__(self):
        return self.course_name

# 学生表
class Student(models.Model):
    sid = models.CharField('学号',max_length=12,primary_key=True)
    name = models.CharField('姓名',max_length=20,unique=True)
    sex = models.BooleanField('性别',choices=((0,'女'),(1,'男')))
    age = models.IntegerField('年龄')
    academy = models.ForeignKey(Academy,on_delete=models.CASCADE,verbose_name='学院')
    major = models.ForeignKey(Major,on_delete=models.CASCADE,verbose_name='专业')
    sclass = models.CharField('班级',max_length=20,help_text='例如: 17-03')
    email = models.EmailField('邮箱',default=None)    # 默认为空   唯一值
    pwd = models.CharField('密码',max_length=20)

    # 修改显示的表的名字
    class Meta:
        verbose_name = '学生'
        verbose_name_plural = '学生信息表'

    def __str__(self):
        return self.sid

# 题库表
class QuestionBank(models.Model):
    id = models.AutoField('序号',primary_key=True)
    major = models.ForeignKey(Major,on_delete=models.CASCADE,verbose_name='专业')
    course = models.ForeignKey(Course,on_delete=models.CASCADE,verbose_name='科目')
    title = models.TextField('题目')
    qtype = models.CharField('题目类型',choices=(('单选','单选'),('多选','多选'),('判断','判断')),max_length=40)
    a = models.CharField('A选项',max_length=40)
    b = models.CharField('B选项',max_length=40)
    c = models.CharField('C选项',max_length=40)
    d = models.CharField('D选项',max_length=40)
    answer = models.CharField('答案',choices=(('A','A'),('B','B'),('C','C'),('D','D')),max_length=4)
    difficulty = models.CharField('难度',choices=(('easy','简单'),('middle','中等'),('difficult','难')),max_length=10)
    score = models.IntegerField('分值')

    class Meta:
        # 选择这个表之后显示的名字
        verbose_name = '题库'
        # 显示的表名
        verbose_name_plural = '题库'

    def __str__(self):
        return '<%s:%s>' % (self.course, self.title)

# 试卷表
class TestPaper(models.Model):
    id = models.AutoField('序号',primary_key=True)
    title = models.CharField('题目',max_length=40,unique=True)
    pid = models.ManyToManyField(QuestionBank)
    course = models.ForeignKey(Course,on_delete=models.CASCADE,verbose_name='科目')
    major = models.ForeignKey(Major,on_delete=models.CASCADE,verbose_name='考卷适合专业')
    time = models.IntegerField('考试时长',help_text='单位是分钟')
    examtime = models.DateTimeField('上次考试时间')

    class Meta:
        # 选择这个表之后显示的名字
        verbose_name = '试卷'
        verbose_name_plural = '试卷'

# # 学生成绩表
class Record(models.Model):
    id = models.AutoField('序号',primary_key=True)
    sid = models.ForeignKey(Student,on_delete=models.CASCADE,verbose_name='学号',related_name='stu_xuehao')
    course = models.ForeignKey(Course,on_delete=models.CASCADE,verbose_name='考试科目',related_name='stu_course')
    grade = models.FloatField('成绩')
    rtime = models.DateTimeField('考试时间',blank=True,null=True)

    class Meta:
        verbose_name = '学生成绩'
        verbose_name_plural = '学生成绩'

    def __str__(self):
        return '<%s:%s>' % (self.sid,self.grade)

编写好了Model后,接下来就需要进行数据迁移。迁移是Django对模型所做的更改传递到数据库中的方式。

注意,每当对数据库进行了更改(添加、修改、删除等)操作,都需要进行数据迁移。

Django的迁移代码是由模型文件自动生成的,它本质上只是个历史记录,Django可以用它来进行数据库的滚动更新,通过这种方式使其能够和当前的模型匹配。

在命令行中输入命令让 Django知道我们自定义模型有一些变更,并根据我们自定义app的模型生成创建数据表的脚本:

python manage.py makemigrations

最后通过命令创建app模型对应的数据库表:

python manage.py migrate

定义视图函数

Django 中视图的概念是「一类具有相同功能和模板的网页的集合」。

比如,在一个考试系统中,我们可能需要如下几个视图:

登录:输入用户和密码,根据校验结果进行登录处理。

考试:展示考试试题及选项,根据选择的结果记录考试成绩。

这些需求都靠视图(View)来完成。

每一个视图表现为一个简单的Python函数,它需要要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse对象,或者抛出一个异常,比如 Http404 。

视图函数中的request与网页发来的请求有关,里面包含get或post的内容、用户浏览器、系统等信息。

根据系统设计过程中需要的功能,我们在exam/views.py文件中创建如下几个视图函数:

studentLogin:

此视图函数用户登录,调用此函数时系统将会检验输入的表单的用户名和密码是否匹配,如果匹配则将用户信息存入session,同时跳转到首页(考试信息)。

# 学生登录
def studentLogin(request):
    if request.method == 'POST':
        # 获取表单信息
        sid = request.POST.get('sid')
        password = request.POST.get('password')
        print("sid", sid, "password", password)
        # 通过学号获取该学生实体
        student = models.Student.objects.get(sid=sid)
        print(student)
        if password == student.pwd:  # 登录成功
            request.session['username']=sid    #user的值发送给session里的username
            request.session['is_login']=True   #认证为真
            # 查询考试信息
            paper = models.TestPaper.objects.filter(major=student.major)
            # 查询成绩信息
            grade = models.Record.objects.filter(sid=student.sid)

            # 渲染index模板
            return render(request, 'index.html', {'student': student, 'paper': paper, 'grade': grade})
        else:
            return render(request,'login.html',{'message':'密码不正确'})
    elif request.method == 'GET':
        return render(request, 'login.html')
    else:
        return HttpResponse("请使用GET或POST请求数据")

index:

根据登录函数传的参数,显示该用户可以参加的考试试卷,在该页面可以点击开始考试按钮进行考试。

# 首页
def index(request):
    if request.session.get('is_login',None):  #若session认证为真
        username = request.session.get('username',None)
        print(username )
        student = models.Student.objects.get(sid=username)
        # 查询考试信息
        paper = models.TestPaper.objects.filter(major=student.major)
        return render(request, 'index.html',{'student': student,'paper': paper})
    else:
        return render(request, 'index.html')

userfile:

显示当前用户的个人信息

def userfile(request):
    if request.session.get('is_login',None):  #若session认证为真
        username = request.session.get('username',None)
        print(username )
        student = models.Student.objects.get(sid=username)
        # 查询考试信息
        paper = models.TestPaper.objects.filter(major=student.major)
        return render(request, 'userfile.html',{'student': student})

stulogout:

退出登录,清楚Session信息

#学生退出登录
def stulogout(request):
    # logout(request)
    request.session.clear()
    url = reverse('exam:index')
    return redirect(url)

startExam:

开始考试,跳转到考试页面

# 考试信息
def startExam(request):
    sid = request.GET.get('sid')
    title = request.GET.get('title')  # 试卷名字 唯一
    subject1 = request.GET.get('subject')  # 考试科目
    # 获取学生信息
    student = models.Student.objects.get(sid=sid)
    # 试卷信息
    paper = models.TestPaper.objects.filter(title=title,course__course_name=subject1)
    context = {
        'student': student,
        'paper': paper,
        'title': title,
        'subject':subject1,
        'count': paper.count()   # 数据表中数据的条数
    }
    return render(request, 'exam.html', context=context)

examinfo:

显示考试成绩页面

def examinfo(request):
    if request.session.get('is_login',None):  #若session认证为真
        username = request.session.get('username',None)
        student = models.Student.objects.get(sid=username)
        # 查询成绩信息
        grade = models.Record.objects.filter(sid=student.sid)
        return render(request, 'examinfo.html',{'student': student,'grade': grade})
    else:
        return render(request, 'examinfo.html')

calculateGrade:

交卷时自动计算考试成绩,并存入数据库

# 计算考试成绩
def calculateGrade(request):
    if request.method == 'POST':
        sid = request.POST.get('sid')
        subject1 = request.POST.get('subject')
        student = models.Student.objects.get(sid=sid)
        paper = models.TestPaper.objects.filter(major=student.major)
        grade = models.Record.objects.filter(sid=student.sid)
        course = models.Course.objects.filter(course_name=subject1).first()
        now =  datetime.now()
        # 计算考试成绩
        questions = models.TestPaper.objects.filter(course__course_name=subject1).
        values('pid').values('pid__id','pid__answer','pid__score')

        stu_grade = 0  # 初始化一个成绩
        for p in questions:
            qid = str(p['pid__id'])
            stu_ans = request.POST.get(qid)
            cor_ans = p['pid__answer']
            if stu_ans == cor_ans:
                stu_grade += p['pid__score']
        models.Record.objects.create(sid_id=sid, course_id=course.id, grade=stu_grade,rtime=now)
        context = {
            'student': student,
            'paper': paper,
            'grade': grade
        }
        return render(request, 'index.html', context=context)

配置访问路由URL

有了视图后,我们需要将视图函数和Web网页链接对应起来。

url可以理解为访问网站时输入的网址链接,配置好url后Django才知道怎样定位app。

打开DjangoExam/urls.py,输入如下代码:

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
from exam import views

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$',views.index),#默认访问首页
    url('index/',views.index,name='index'),
    url('studentLogin/',views.studentLogin,name='studentLogin'),#学生登录
    url('startExam/',views.startExam,name='startExam'),#开始考试
    url('calculateGrade/',views.calculateGrade,name='calculateGrade'),#考试评分
    path('stulogout/',views.stulogout,name='stulogout'), # 学生退出登录
    path('userfile/',views.userfile,name='userfile'), # 个人信息
    path('examinfo/',views.examinfo,name='examinfo'), # 考试信息
]

通过配置如上URL,Django 将会根据用户请求的 URL 来选择使用哪个视图。

静态资源准备及配置

本系统前后端不分离,前端框架选用当前比较受欢迎的Bootstrap4,为了快速开发,本系统所有的页面都使用原生Bootstrap进行开发,未采用第三方的模板和主题。

下载 Bootstrap · Bootstrap v4 中文文档 v4.6 | Bootstrap 中文网下载 Bootstrap 以获得编译后的 CSS 和 JavaScript 文件、源码,或者通过你所喜欢的软件包管理器,例如 npm、RubyGems 等,将 Bootstrap 添加到你的项目中。[这里是图片008]https://v4.bootcss.com/docs/getting-started/download/

因为bootstrap.js依赖 jquery.jspopper.js才能正常运行,因此我们也需要一并下载保存。

由于popper.js版本兼容问题,本系统采用cdn 远程引入的形式。

附上官网下载链接(进入下载页面,复制粘贴代码到新文件即可):

Download jQuery | jQuery[这里是图片009]https://jquery.com/download/

在项目根目录下新建一个文件夹static用于存放前端模板静态资源。

把刚才Bootstrap解压出来的css和js两个文件夹复制到static文件夹去。

把刚刚解压出来的jQuery文件夹复制到static文件夹去。

完成后Static文件夹结构如下图:

准备好静态资源后,我们还需要在Django中指定静态文件的存放位置,这样才能够在模板中正确引用它们。

在DjangoExam/settings.py 中进行如下配置:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),  # 添加此项
]

模板创建

在创建模板之前,我们先在根目录下新建一个文件夹templates用于存放我们的所有的模板文件。

模板位置也同样需要进行配置指定模板的存放位置,在DjangoExam/settings.py 中进行如下配置:

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',
            ],
        },
    },
]

接着我们在模板文件中新建三个文件:

  • base.html:是整个项目的模板基础,所有的网页都从它继承;
  • header.html:是网页顶部的导航栏;
  • footer.html:是网页底部的注脚。

分别编写三个静态HTML文件代码如下:

templates/base.html:

<!--    载入静态文件-->
{% load static %}
<!-- 网站主语言 -->
<html lang="zh-cn">
<head>
    <!-- 网站采用的字符编码 -->
    <meta charset="utf-8">
    <!-- 预留网站标题的位置 -->
    <title>{% block title %}{% endblock %}</title>
    <!-- 引入bootstrap的css文件 -->
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
</head>
<body>
<!-- 引入导航栏 -->
{% include 'header.html' %}
<!-- 预留具体页面的位置 -->
{% block content %}{% endblock content %}
<!-- 引入注脚 -->
{% include 'footer.html' %}
<!-- bootstrap.js 依赖 jquery.js 和popper.js,因此在这里引入 -->
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="{% static 'jquery/jquery-3.6.0.js' %}"></script>
<!--
    popper.js 采用 cdn 远程引入,意思是你不需要把它下载到本地。
    在实际的开发中推荐静态文件尽量都使用 cdn 的形式。
    教程采用本地引入是为了让读者了解静态文件本地部署的流程。
-->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1-lts/dist/umd/popper.min.js"></script>

<!-- 引入bootstrap的js文件 -->
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</body>

</html>

templates/header.html:

<!-- 定义导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    <div class="container">
        <!-- 导航栏商标 -->
        <a class="navbar-brand" href="#">在线考试</a>
        <!-- 导航入口 -->
        <div>
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a class="nav-link" href="/index/">首页</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/examinfo/">考试记录</a>
                </li>
                <!-- Django的 if 模板语句 -->
                {% if request.session.username %}
                <!-- 如果用户已经登录,则显示用户名下拉框 -->
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        {{ request.session.username }}
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <a class="dropdown-item" href="/userfile/">个人信息</a>
                        <a class="dropdown-item" href="/stulogout/">退出登录</a>
                    </div>
                </li>
                <!-- 如果用户未登录,则显示 “登录” -->
                {% else %}
                <li class="nav-item">
                    <a class="nav-link" href="/studentLogin/">登录</a>
                </li>
                <!-- if 语句在这里结束 -->
                {% endif %}
                <li class="nav-item">
                    <a class="nav-link" href="/admin">管理员</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

templates/footer.html:

{% load static %}
<!-- Footer -->
<div>
    <br><br><br>
</div>
<footer class="py-3 bg-dark fixed-bottom">
    <div class="container">
        <p class="m-0 text-center text-white">Copyright &copy; DjangoExam 2021</p>
    </div>
</footer>

上述三个文件是网站页面的通用组件模块,基本上每个页面都不会变,所以我们把他们独立出来。

我们编写Django后续的页面模板时可以直接继承对应的通用模板组件。

接下来我们在三个通用组件的基础上分别编写各个视图对应的模板页面:

限于篇幅,放一些关键代码供参考:

index.html

<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load static %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
在线考试系统
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<div class="container">
    <div class="container">
        <br>
        <h3>考试信息</h3>
        <div class="container">
            <div class="row mt-4">
                {% for paper1 in paper %}
                <!-- 文章内容 -->
                <div class="col-6 mb-6">
                    <!-- 卡片容器 -->
                    <div class="card">
                        <!-- 标题 -->
                        <h4 class="card-header">{{ paper1.title }}</h4>
                        <!-- 摘要 -->
                        <div class="card-body">
                            <h4 class="card-title">{{ paper1.course }}</h4>
                            <p class="card-text">{{ paper1.examtime  }}</p>
                            <a href="/startExam/?sid={{ student.sid }}&title={{ paper1.title }}&subject={{ paper1.course }}"  class="card-link">开始考试</a>
                        </div>
                    </div>
                </div>
                {% endfor %}
            </div>
        </div>
        <p></p>
    </div>
</div>
{% endblock content %}

login.html

{% extends "base.html" %} {% load static %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
  <div class="row justify-content-md-center">
    <div class="col-4">
      <br>
      <form method="post" action="/studentLogin/">
<!--        {% csrf_token %}-->
        <!-- 账号 -->
        <div class="form-group">
          <label >学生学号</label>
          <input type="text" class="form-control" name="sid" placeholder="输入学号">
        </div>
        <!-- 密码 -->
        <div class="form-group">
          <label for="password">密码</label>
          <input type="password" class="form-control" id="password" name="password" placeholder="输入密码">
        </div>
        <!-- 提交按钮 -->
        <button type="submit" class="btn btn-primary">登录</button>
        <div class="form-group">
        <br>
        <br>
        </div>
      </form>
    </div>
  </div>
</div>
{% endblock content %}

exam.html

<div class="container">
            {% for paper1 in paper %}
            {% for test in paper1.pid.all %}
            <div class="row bg-light">
                <div class="col-12">
<!--                <div class="card">-->
<!--                    <div class="card-body h-10">-->
                        <div id="{{ forloop.counter }}">
                                <b>{{ forloop.counter}}.</b><span>({{ test.score }}分)</span>
                                <b>{{ test.title }}</b>
                                <ul>
                                    <li class="option">
                                        <input type="radio" class="radioOrCheck" name="{{ test.id }}"
                                               value="A"/>
                                        <label>A.
                                            <p class="ue" style="display: inline;">{{ test.a }}</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.b }}</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.c}}</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.d }}</p>
                                        </label>
                                    </li>
                                </ul>
<!--                        </div>-->
<!--                    </div>-->
                    </div>
                </div>
            </div>
                {% endfor %}
                {% endfor %}
            </div>

examinfo.html

<div class="container">
    <div class="container">
        <br>
        <h3>考试成绩</h3>
        <p></p>
        <table class="table">
            <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成绩</th>
                <th>考试时间</th>
            </tr>
            </thead>
            <tbody>
            {% for grade1 in grade %}
            <tr class="table">
                <td>{{ student.name }}</td>
                <td>{{ grade1.course }}</td>
                <td>{{ grade1.grade }}</td>
                <td>{{ grade1.rtime|date:"Y-m-d H:i:s"}}</td>
            </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>
</div>

userfile.html

<div class="container">
    <br>
    <div class="row justify-content-md-center">
        <div class="col-8">
      <div class="panel panel-info">
          <div class="panel-heading">
              <h3 class="panel-title">个人信息</h3>
          </div>
          <div class="panel-body">
              <table class="table table-borderless">
                  <tbody>
                  <tr>
                      <td>学号</td>
                      <td>{{ student.sid }}</td>
                  </tr>
                  <tr class="table">
                      <td>姓名</td>
                      <td>{{ student.name }}</td>
                  </tr>
                  <tr class="table">
                      <td>性别</td>
                      {% if student.sex%}
                      <td>男</td>
                      {% else %}
                      <td>女</td>
                      {% endif %}
                  </tr>
                  <tr class="table">
                      <td>学院</td>
                      <td>{{ student.academy }}</td>
                  </tr>
                  <tr class="table">
                      <td>专业</td>
                      <td>{{ student.major }}</td>
                  </tr>

                  <tr class="table">
                      <td>邮箱地址</td>
                      <td>{{ student.email }}</td>
                  </tr>
                  <tr class="table">
                      <td>出生日期</td>
                      <td>{{ student.birth }}</td>
                  </tr>
                  </tbody>
              </table>
          </div>
      </div>
        </div>
    </div>
</div>

Django后台启用配置

Django自带后台功能,我们只需要两步就可以使用后台功能直接更新我们的后台数据表信息。

1、创建超级用户

在命令行输入:python manage.py createsuperuser

根据提示信息输入用户名,邮箱和密码后系统就创建了一个超级用户。

2、注册模型到admin中

打开exam/admin.py输入如下代码将所有的模型都注册到admin中,我们就可以在Django自带的后台中更新我们的数据表了。

from django.contrib import admin

# Register your models here.

# 修改名称
admin.site.site_header='在线考试系统后台'
admin.site.site_title='在线考试系统'

from exam.models import Academy,Major, Course,Student,QuestionBank,TestPaper,Record

admin.site.register([Academy,Major,Course,Student,QuestionBank,TestPaper,Record])

运行服务器测试效果

在Windows命令行输入:

python manage.py runserver

运行服务器后在浏览器中输入我们之前配置的首页对应的URL地址:

http://127.0.0.1:8000/index


结语:

本系统仅仅实现了考试管理系统的部分功能,还有很多的功能可以添加到此系统中。

比如:

可以引入教师管理模块,针对教师和学生端实现不同的功能需求。

针对成绩部分,可以引入图表,进行可视化的数据分析等等。


最后,原创不易,希望大家能够点赞支持下。