项目实战——《在线考试系统》
项目实战——《在线考试系统》
1.目录结构
D:.
└─onlineExam
    ├─.idea
    │  ├─dataSources
    │  └─inspectionProfiles
    ├─onlineExam
    │  └─__pycache__
    ├─static
    │  ├─bootstrap-4.3.1-dist
    │  │  ├─css
    │  │  └─js
    │  ├─css
    │  └─js
    ├─student
    │  ├─migrations
    │  │  └─__pycache__
    │  └─__pycache__
    ├─templates
    └─__pycache__
2.数据库分析
学生表 student
教师表 teacher
试题库表 question(题库中均为单项选择题)
试卷表 paper
学生成绩表 grade
- 学生表和成绩表,1个学生可参加多门考试,会有多个成绩,学生表:成绩表=1:n
- 教师表和试卷表,1个教师会发布多套试卷,但1套试卷只能由1位教师发布,教师表:试卷表=1:n
- 试卷表和题库表,1套试卷里包含多道题,题库里的每道题也可出现在多个试卷中,故试卷表:题库表=n:m
 数据表:
| student | teacher | question | paper | grade | 
|---|---|---|---|---|
| id (PK) | id (PK) | id(PK) | id(FK) | id(PK) | 
| name | name | subject | subject | grade | 
| sex | sex | title | major | sid_id(FK) | 
| dept | dept | optionA | examtime | subject | 
| major | optionB | tid_id(FK) | ||
| password | password | optionC | answer | |
| birth | optionD | |||
| birth | lever | |||
| score | 
3.环境
Django3.0.3 + python3.9 + mysql-8.0.11-winx64
4.项目代码
onlineExam/onlineExam/settings.py
#自动生成,仅需做部分修改
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = 'q5qv4a+i=&=#l=!3qzgd6$6xw88a48@3@3&n#%8h$r!w!=kva8'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
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', 取消csrf验证
    '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
#配置mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testonline',#使用数据库的名称
        'USER':'root',#用户名
        'PASSWORD':'root',#密码
        'HOST':'127.0.0.1',#地址
        'PORT':'3306'#端口号
    }
}
# Password validation
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
#修改默认网站语言为中文
LANGUAGE_CODE = 'zh-hans'
#修改时区为shanghai
TIME_ZONE = 'Asia/Shanghai'#只找到设置为上海的方法
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
#添加static文件夹
STATIC_URL = '/static/'
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,'static'),
]
onlineExam/onlineExam/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'^studentLogin/',views.studentLogin),
    #教师登陆
    url(r'^teacherLogin/',views.teacherLogin),
    #默认访问首页
    url(r'^$',views.index),
    url(r'^toIndex/$',views.toIndex),
    url('showGrade',views.showGrade),
    url('queryStudent',views.queryStudent),
    url(r'^startExam/$',views.startExam),
    url(r'^calGrade/$',views.calGrade),
    url(r'^logout/$',views.logOut),
]
onlineExam/onlineExam/wsgi.py
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'onlineExam.settings')
application = get_wsgi_application()
onlineExam/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)#使用装饰器注册model,@admin.register(Student)修饰StudentAdmin注册类,@语法糖,我又不是很清楚
#装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
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']#指定列表过滤器,右边将会出现一个快捷的过滤选项
@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')
@admin.register(Paper)
class PaperAdmin(admin.ModelAdmin):
    list_display = ('tid','major','subject','examtime')
    list_display_links = ('major','subject','examtime')
@admin.register(Grade)
class GradeAdmin(admin.ModelAdmin):
    list_display = ('sid','subject','grade',)
    list_display_links = ('sid','subject','grade',)
    # fk_fields = ['sid']
onlineExam/student/apps.py
from django.apps import AppConfig
class StudentConfig(AppConfig):
    name = 'student'
onlineExam/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
onlineExam/student/views.py
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')
def toIndex(request):
    return render(request,'index.html')
# 学生登陆 视图函数
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':'密码不正确'})
# 教师登陆 视图函数
def teacherLogin(request):
    if request.method == 'POST':
        teaId = request.POST.get('id')
        password = request.POST.get('password')
        # print("id", teaId, "password", password)
        teacher=models.Teacher.objects.get(id=teaId)
        print(teacher)
        if password == teacher.password:  # 登录成功
            # 实现成绩统计功能
            #在试卷表 paper 找到该老师发布的试题
            paper=models.Paper.objects.filter(tid=teacher.id)
            data1=models.Grade.objects.filter(subject='软件工程',grade__lt=60).count()
            data2=models.Grade.objects.filter(subject='软件工程',grade__gte=60,grade__lt=70).count()
            data3 = models.Grade.objects.filter(subject='软件工程', grade__gte=70, grade__lt=80).count()
            data4 = models.Grade.objects.filter(subject='软件工程', grade__gte=80, grade__lt=90).count()
            data5 = models.Grade.objects.filter(subject='软件工程', grade__gte=90).count()
            data6 = models.Grade.objects.filter(subject='数据库原理', grade__lt=60).count()
            data7= models.Grade.objects.filter(subject='数据库原理', grade__gte=60, grade__lt=70).count()
            data8= models.Grade.objects.filter(subject='数据库原理', grade__gte=70, grade__lt=80).count()
            data9 = models.Grade.objects.filter(subject='数据库原理', grade__gte=80, grade__lt=90).count()
            data10= models.Grade.objects.filter(subject='数据库原理', grade__gte=90).count()
            data_1={'data1':data1,'data2':data2,'data3':data3,'data4':data4,'data5':data5}
            data_2 = {'data6': data6, 'data7': data7, 'data8': data8, 'data9': data9, 'data10': data10}
            print("数量:",data2)
            return render(request, 'teacher.html', {'teacher': teacher, 'paper':paper,'data_1':data_1,'data_2':data_2})
        else:
            return render(request, 'index.html', {'message': '密码不正确'})
#教师查看成绩
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})
#教师按条件查询学生
def queryStudent(request):
    #获取教师查询的条件值
    sid=request.GET.get('id')
    sex=request.GET.get('sex')
    subject=request.GET.get('subject')
    #获取老师的id
    tid=request.GET.get('tid')
    teacher = models.Teacher.objects.get(id=tid)
    paper = models.Paper.objects.filter(tid=teacher.id)
    # print(sid,sex,subject)
    from django.db import connection,transaction
    cursor=connection.cursor()
    sql="select * from grade,student where student.id=grade.sid_id " \
        "and student.id like %s and grade.subject like %s and student.sex like %s and '1'='1'"
    val=('%'+sid+'%','%'+subject+'%','%'+sex+'%')
    cursor.execute(sql,val)
    result=dictfetchall(cursor)
    # print(result)
    return render(request,'teacher.html',{'teacher':teacher,'result':result,'paper':paper})
#将使用原生sql语句查到的结果由tuple类型转换为dictionary(字典)类型
def dictfetchall(cursor):
    "将游标返回的结果保存到一个字典对象中"
    desc = cursor.description
    return [
    dict(zip([col[0] for col in desc], row))
    for row in cursor.fetchall()
    ]
#学生考试 的视图函数
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.html模版传过来的数据计算成绩
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})
# 教师退出
def logOut(request):
    return redirect('/toIndex/')
onlineExam/templates/exam.html
from django.test import TestCase
#没啥用
# Create your tests here.
onlineExam/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
{#    <link rel="icon" href="http://v3.bootcss.com/favicon.ico">#}
    <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 class="nav-item active">#}
{#            <a class="nav-link" href="/toLogin/">学生登陆</a>#}
{##}
{#        </li>#}
{##}
{#            <li class="nav-item active">#}
{#            <a class="nav-link" href="/admin/">教师登陆</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>
onlineExam/templates/showGrade.html
<!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>
    <script src="../static/js/echarts.min.js"></script>
    <title>成绩</title>
</head>
<body>
 <table class="table">
            <thead>
              <tr>
                <th>学生学号</th>
                <th>考试科目</th>
                  <th>成绩</th>
              </tr>
            </thead>
            <tbody>
            {#   遍历字典  grade #}
            {% for grade in grade %}
            <tr class="table-info">
                <td>{{ grade.sid }}</td>
                <td>{{ grade.subject }}</td>
                <td>{{ grade.grade }}</td>
                </tr>
            {% endfor %}
            </tbody>
          </table>
<div id="main1" style="width: 700px;height:500px;"></div>
 <script type="text/javascript">
     var myChart1=echarts.init(document.getElementById('main1'));
    myChart1.setOption({
    title : {
        text: '{{ subject }}',
        subtext: '',
        x:'center'
    },
    tooltip : {
        trigger: 'item',
        formatter: "{a} <br/>{b} : {c} ({d}%)"
    },
    legend: {
        orient: 'vertical',
        left: 'left',
    },
    series : [
        {
            name: '{{ subject }}',
            type: 'pie',
            radius : '55%',
            center: ['50%', '60%'],
            data:[
                {value:{{ data.data1 }}, name:'<60'},
                {value:{{ data.data2}}, name:'60-70'},
                {value:{{ data.data3 }}, name:'70-80'},
                {value:{{ data.data4 }}, name:'80-90'},
                {value:{{ data.data5 }}, name:'>90'}
            ],
            itemStyle: {
                emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
            }
        }
    ]
})
 </script>
</body>
</html>
teacher.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
{#     <link rel="icon" href="http://v3.bootcss.com/favicon.ico">#}
    <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/echarts.min.js"></script>
    <title>教师页面</title>
</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" href="/toLogin/">学生登陆</a>#}
{##}
{#        </li>#}
{##}
{#            <li class="nav-item active">#}
{#            <a class="nav-link" href="/admin/">教师登陆</a>#}
{#            </li>#}
        <li>
            <a href="/logout/"><button data-target="#myModal" data-toggle="modal" class="btn btn-primary">退出</button></a>
        </li>
        <li style="position: fixed;right:70px; font-size: 40px;color: #9fcdff">{{ message }}{{ teacher.name }}</li>
    </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 active">
      <a class="nav-link" data-toggle="pill" href="#menu2">成绩查询</a>
    </li>
      <li class="nav-item">
      <a class="nav-link" href="/admin/student/paper/add/">组卷</a>
    </li>
  </ul>
  <!-- Tab panes -->
  <div class="tab-content">
    <div id="home" class="container tab-pane active"><br>
      <h3>个人信息</h3>
      <p>登陆成功后可查看我的个人信息哦.</p>
        <table class="table">
    <thead>
      <tr>
        <th>属性</th>
        <th>信息</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>教工号</td>
        <td>{{ teacher.id }}</td>
      </tr>
      <tr class="table-primary">
        <td>姓名</td>
        <td>{{ teacher.name }}</td>
      </tr>
      <tr class="table-success">
        <td>性别</td>
        <td>{{ teacher.sex }}</td>
      </tr>
      <tr class="table-danger">
        <td>学院</td>
        <td>{{ teacher.dept }}</td>
      </tr>
      <tr class="table-warning">
        <td>邮箱地址</td>
        <td>{{ teacher.email }}</td>
      </tr>
      <tr class="table-active">
        <td>出生日期</td>
        <td>{{ teacher.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>
              </tr>
            </thead>
            <tbody>
            {#   遍历字典  paper #}
            {% for paper1 in paper %}
             <tr class="table-info">
                  <td>{{ teacher.name }}</td>
                  <td>{{ paper1.subject }}</td>
                  <td>{{ paper1.examtime }}</td>
                 <td><a href="/showGrade/?subject={{ paper1.subject }}">
                     <button type="button" class="btn btn-primary"
                 data-toggle="collapse" data-target="#demo">查看学生成绩</button></a>
                 </td>
            {#          <td><button class="btn btn-primary">开始考试</button></td>#}
              </tr>
            {% endfor %}
            </tbody>
        </table>
    <div id="main" style="width: 800px;height:500px;"></div>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
        // 指定图表的配置项和数据
        var option = {
    legend: {},
    tooltip: {},
    dataset: {
        // 提供一份数据。
        source: [
            ['product', '软件工程', '数据库原理'],
            ['<60', {{ data_1.data1 }}, {{ data_2.data6 }}],
            ['60<=成绩<70', {{ data_1.data2 }}, {{ data_2.data7 }}],
            ['70<=成绩<80', {{ data_1.data3 }}, {{ data_2.data8 }}],
            ['80<=成绩<90', {{ data_1.data4 }}, {{ data_2.data9 }}],
            ['90<=成绩', {{ data_1.data5 }}, {{ data_2.data10 }}]
        ]
    },
    // 声明一个 X 轴,类目轴(category)。默认情况下,类目轴对应到 dataset 第一列。
    xAxis: {type: 'category'},
    // 声明一个 Y 轴,数值轴。
    yAxis: {},
    // 声明多个 bar 系列,默认情况下,每个系列会自动对应到 dataset 的每一列。
    series: [
        {type: 'bar'},
        {type: 'bar'}
    ]
};
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>
    </div>
    <div id="menu2" class="container tab-pane fade"><br>
      <h3>考试成绩</h3>
{#        form表单#}
      <div class="container">
          <form action="/queryStudent/" method="get">
              <input type="hidden" name="tid" value="{{ teacher.id }}">
              <div class="row">
                  <div class="col-sm-2">
                      <div class="form-group">
                          <label>学号</label>
                          <input type="text" name="id" class="form-control" placeholder="请输入学号">
                      </div>
                  </div>
                  <div class="col-sm-2 offset-1">
                      <label for="">性别</label>
                      <div class="radio">
{#                          使用单选框的checked属性,默认 全部 单选按钮被选中#}
                            <label><input type="radio" name="sex" value="" checked>全部</label>
                        </div>
                      <div class="radio">
                            <label><input type="radio" name="sex" value="男" >男</label>
                        </div>
                        <div class="radio">
                          <label><input type="radio" name="sex" value="女">女</label>
                        </div>
                  </div>
                  <div class="col-sm-2 offset-1">
                      <label for="">科目</label>
                      <input type="text" name="subject" placeholder="输入科目名称">
                  </div>
                  <div class="col-sm-2 offset-2">
                      <button class="btn btn-success" type="submit">search</button>
                  </div>
              </div>
          </form>
      </div>
{#    搜到的学生信息#}
        <div class="container">
            <table class="table">
                <thead>
                  <tr>
                      <th>学号</th>
                    <th>姓名</th>
                      <th>专业</th>
                    <th>科目</th>
                    <th>成绩</th>
                  </tr>
                </thead>
                <tbody>
                {% for result1 in result %}
                <tr class="table-primary">
                    <td>{{ result1.id }}</td>
                    <td>{{ result1.name }}</td>
                    <td>{{ result1.major }}</td>
                    <td>{{ result1.subject }}</td>
                    <td>{{ result1.grade }}</td>
                </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
    <div id="menu3" class="container tab-pane fade"><br>
      <h3>题库</h3>
      <p>题库</p>
    </div>
  </div>
</div>
</body>
</html>
onlineExam/manage.py
import os
import sys
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'onlineExam.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号