溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

利用Django框架編寫一個(gè)在線考試系統(tǒng)

發(fā)布時(shí)間:2020-12-01 16:12:31 來源:億速云 閱讀:688 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章為大家展示了利用Django框架編寫一個(gè)在線考試系統(tǒng),內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

1.Django的簡介

Django是一個(gè)基于MVC構(gòu)造的框架。但是在Django中,控制器接受用戶輸入的部分由框架自行處理,所以 Django 里更關(guān)注的是模型(Model)、模板(Template)和視圖(Views),稱為 MTV模式。它們各自的職責(zé)如下:

層次職責(zé)
模型(Model),即數(shù)據(jù)存取層模型(Model),即數(shù)據(jù)存取層
模板(Template),即表現(xiàn)層處理與表現(xiàn)相關(guān)的決定: 如何在頁面或其他類型文檔中進(jìn)行顯示。
視圖(View),即業(yè)務(wù)邏輯層存取模型及調(diào)取恰當(dāng)模板的相關(guān)邏輯。模型與模板的橋梁。

Django里重要的概念有:

  • 路由映射

  • 視圖函數(shù)

  • 模板渲染

  • Django自帶的ORM操作(對象關(guān)系映射)

2.項(xiàng)目的設(shè)計(jì)思路

1.在線考試系統(tǒng)需求如下:
(1)系統(tǒng)登錄:驗(yàn)證登錄用戶的身份,根據(jù)用戶身份進(jìn)入不同的頁面。
(2)學(xué)生管理:供管理員使用,用于維護(hù)學(xué)生基本信息。
(3)老師管理:供管理員使用,用于維護(hù)教師的基本信息。
(4)試題管理:供教師管理,用于維護(hù)題庫。
(5)組卷:供教師使用,教師可以根據(jù)考試科目,從題庫中選擇一些符合條件的試題,形成一份試卷。為了方便教師組卷,應(yīng)提供方便的查詢功能,使教師能查詢不同要求的試題。
(6)在線考試:供學(xué)生使用,根據(jù)學(xué)生的班級和登錄時(shí)間顯示應(yīng)考科目的試卷內(nèi)容。試卷完成提交或考試時(shí)間到,不再允許學(xué)生修改試卷;實(shí)現(xiàn)自動(dòng)評閱,記錄學(xué)生的考試成績,并將評閱結(jié)果提供給學(xué)生。
(7)成績統(tǒng)計(jì):供教師使用,按照科目、班級等統(tǒng)計(jì)學(xué)生的考試成績。
(8)成績查詢:供教師和學(xué)生使用,提供不同查詢方式,使教師和學(xué)生可以按需查詢考試成績。

2.設(shè)計(jì)思路
(1)確定角色
由需求分析看出,系統(tǒng)有三個(gè)基本角色,學(xué)生、教師、管理員。

  • 管理員負(fù)責(zé)后臺信息的維護(hù)

  • 系統(tǒng)要能實(shí)現(xiàn)自動(dòng)閱卷功能

(2)數(shù)據(jù)庫表的設(shè)計(jì)
因此,我們至少需要如下幾個(gè)表:

  • 學(xué)生表 student

  • 教師表 teacher

  • 題庫表 question(為了方便,題庫中都為單項(xiàng)選擇題)

  • 試卷表 paper

  • 學(xué)生成績表 grade

設(shè)計(jì)完表,我們還需要確定表間的關(guān)系,是1對1(1:1),1對多(1:n),還是多對多(n:m),這很重要,因?yàn)楹竺嫖覀冊趍odels.py中創(chuàng)建表時(shí),需要指出表間關(guān)系。
顯然

  • 學(xué)生表和成績表,1個(gè)學(xué)生可參加多門考試,會(huì)有多個(gè)成績,學(xué)生表和成績表為1:n

  • 教師表和試卷表,1個(gè)教師會(huì)發(fā)布多套試卷,但1套試卷只能由1位教師發(fā)布,教師表和試卷表為1:n

  • 試卷表和題庫表,1套試卷里包含多道題,題庫里的每道題也可出現(xiàn)在多個(gè)試卷中,故試卷表和題庫表為n:m

表的詳細(xì)設(shè)計(jì)如下:(使用MindMaster繪制,有點(diǎn)丑,請忽略,重點(diǎn)寫下自己的思考和思路)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

3.搭建你的開發(fā)環(huán)境

IDE使用PyCharm(profession版的)
python 3.7, Django 2.1.0
數(shù)據(jù)庫為關(guān)系數(shù)據(jù)庫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需要數(shù)據(jù)庫mysql5.6以上),你可以使用pip list來查看版本,使用 pip uninstall django 來卸載django模塊

安裝mysql數(shù)據(jù)庫驅(qū)動(dòng) pip install pymysql
配置好后建立項(xiàng)目

(1) 在PyCharm中建立Django項(xiàng)目

利用Django框架編寫一個(gè)在線考試系統(tǒng)

圖1 建立項(xiàng)目

此處沒有使用虛擬環(huán)境,你也可以選擇 “New environment using”選項(xiàng)來創(chuàng)建一個(gè)虛擬環(huán)境(可以避免多個(gè)項(xiàng)目使用不同模塊的版本時(shí)發(fā)生沖突)

(2)創(chuàng)建app
Tools->Run manage.py task

利用Django框架編寫一個(gè)在線考試系統(tǒng)

在控制臺輸入 startapp student,創(chuàng)建一個(gè)student app,

利用Django框架編寫一個(gè)在線考試系統(tǒng)

之后需要將student app配置在項(xiàng)目的settings.py中,由于我的前臺需要用到css、BootStrap、一些圖片等文件,所以我在項(xiàng)目下建立static文件夾,并將其路徑配置在settings.py文件中。整體目錄如下:

利用Django框架編寫一個(gè)在線考試系統(tǒng)

(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數(shù)據(jù)庫
DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'exam',#使用數(shù)據(jù)庫的名稱
    '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'

#修改時(shí)區(qū)為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 配置你的數(shù)據(jù)庫參數(shù)

  • MIDDLEWARE 注釋掉了 # 'django.middleware.csrf.CsrfViewMiddleware'這一行

  • STATICFILES_DIRS 添加新建的static文件夾

(4)在__init___.py文件添加mysql的驅(qū)動(dòng)模塊

import pymysql
pymysql.install_as_MySQLdb()

4.分模塊詳細(xì)設(shè)計(jì)

(1)建表
在student下的models.py中建表

from django.db import models

# Create your models here.

# 為性別,學(xué)院 指定備選字段
SEX=(
  ('男','男'),
  ('女','女'),
)
DEPT=(
  ('計(jì)算機(jī)與通信學(xué)院','計(jì)算機(jī)與通信學(xué)院'),
  ('電氣與自動(dòng)化學(xué)院','電氣與自動(dòng)化學(xué)院'),
  ('外國語學(xué)院','外國語學(xué)院'),
  ('理學(xué)院','理學(xué)院'),
)

class Student(models.Model):
  id=models.CharField('學(xué)號',max_length=20,primary_key=True)
  name=models.CharField('姓名',max_length=20)
  sex=models.CharField('性別',max_length=4,choices=SEX,default='男')
  dept=models.CharField('學(xué)院',max_length=20,choices=DEPT,default=None)
  major=models.CharField('專業(yè)',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='學(xué)生'
    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('學(xué)院',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選項(xiàng)',max_length=30)
  optionB=models.CharField('B選項(xiàng)',max_length=30)
  optionC=models.CharField('C選項(xiàng)',max_length=30)
  optionD=models.CharField('D選項(xiàng)',max_length=30)
  answer=models.CharField('答案',max_length=10,choices=ANSWER)
  level=models.CharField('等級',max_length=10,choices=LEVEL)
  score=models.IntegerField('分?jǐn)?shù)',default=1)

  class Meta:
    db_table='question'
    verbose_name='單項(xiàng)選擇題庫'
    verbose_name_plural=verbose_name
  def __str__(self):
    return '<%s:%s>'%(self.subject,self.title);

class Paper(models.Model):
  #題號pid 和題庫為多對多的關(guān)系
  pid=models.ManyToManyField(Question)#多對多
  tid=models.ForeignKey(Teacher,on_delete=models.CASCADE)#添加外鍵
  subject=models.CharField('科目',max_length=20,default='')
  major=models.CharField('考卷適用專業(yè)',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數(shù)據(jù)庫中,很簡單,打開 Run manage.py Task,輸入遷移命令
先輸入makemigrate命令,作用是生成sql文件(create table student(id,sex,…) ),執(zhí)行后可在student-> migrations下看到執(zhí)行結(jié)果

利用Django框架編寫一個(gè)在線考試系統(tǒng)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

再輸入migrate命令,執(zhí)行makemigrate生成的sql語句,表就建好了,你可以使用navicat或workBench等工具看到Django為我們建好的表

利用Django框架編寫一個(gè)在線考試系統(tǒng)

(2)創(chuàng)建管理員
繼續(xù)輸入createsuperuser命令創(chuàng)建管理員,以便登陸后臺

利用Django框架編寫一個(gè)在線考試系統(tǒng)

(3)創(chuàng)建模板
在templates中建立index.html模板,作為考試系統(tǒng)首頁.(可去官網(wǎng)下載BootStrap、JQuery)
在頭文件里引入時(shí)注意順序,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>在線考試系統(tǒng)</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" ><h4>在線考試系統(tǒng) 首頁</h4></a>
    </li>


    <li>
      <button data-target="#stuModal" data-toggle="modal" class="btn btn-primary">學(xué)生登陸</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 >{{ student.name }}{{ message }}</li>
    <a href="/logout/" rel="external nofollow" ><li >退出</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" >個(gè)人信息</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>
   <h4>個(gè)人信息</h4>

    <table class="table">
  <thead>
   <tr>
    <th>屬性</th>
    <th>信息</th>

   </tr>
  </thead>
  <tbody>
   <tr>
    <td>學(xué)號</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>學(xué)院</td>
    <td>{{ student.dept }}</td>

   </tr>

    <tr class="table-success">
    <td>專業(yè)</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>
   <h4>考試信息</h4>
   <p></p>
    <table class="table">
  <thead>
   <tr>
     <th>學(xué)號</th>
    <th>姓名</th>
    <th>考試科目</th>
     <th>考試時(shí)間</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>
   <h4>考試成績</h4>
   <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>


{#學(xué)生登錄的模態(tài)對話框#}
<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>
        <h5 class="modal-title">學(xué)生登陸</h5>
      </div>
      <form class="form-horizontal" action="/studentLogin/" method="post">
      <div class="modal-body">

          <div class="form-group">
            <label class="col-sm-3 control-label">學(xué)生學(xué)號</label>
            <div class="col-sm-9">
              <input type="text" class="form-control" name="id" placeholder="輸入學(xué)號">
            </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>

{#老師登錄的模態(tài)對話框#}
<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>
        <h5 class="modal-title">教師登陸</h5>
      </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="輸入學(xué)號">
            </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使用{{ }}來使用后臺傳來的數(shù)據(jù)
(4)創(chuàng)建視圖函數(shù)
在student->views.py中創(chuàng)建進(jìn)入首頁的視圖函數(shù)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')

將視圖函數(shù)配置在路由中,打開項(xiàng)目的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),
  #默認(rèn)訪問首頁
  url(r'^$',views.index),
]

r表示使用正則表達(dá)式解析url地址,^表示開始,$表示結(jié)束,views.index表示調(diào)用視圖函數(shù)index
(5)啟動(dòng)服務(wù)器(可以看到效果了)
兩種方式啟動(dòng)服務(wù)器:執(zhí)行runserver命令,或點(diǎn)擊綠色小圖標(biāo)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

點(diǎn)擊網(wǎng)址,默認(rèn)8000端口,成功后如下圖

利用Django框架編寫一個(gè)在線考試系統(tǒng)

我們還需要定制自己的后臺,在student->admin.py中注冊各模塊

from django.contrib import admin
from .models import Student,Teacher,Paper,Question,Grade
# Register your models here.
# 修改名稱
admin.site.site_header='在線考試系統(tǒng)后臺'
admin.site.site_title='在線考試系統(tǒng)'

@admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
  list_display = ('id','name','sex','dept','major','password','email','birth')# 要顯示哪些信息
  list_display_links = ('id','name')#點(diǎn)擊哪些信息可以進(jìn)入編輯頁面
  search_fields = ['name','dept','major','birth']  #指定要搜索的字段,將會(huì)出現(xiàn)一個(gè)搜索框讓管理員搜索關(guān)鍵詞
  list_filter =['name','dept','major','birth']#指定列表過濾器,右邊將會(huì)出現(xiàn)一個(gè)快捷的過濾選項(xiàng)

對其他4個(gè)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')

刷新,點(diǎn)擊首頁管理員超鏈接,進(jìn)入后臺,使用前邊創(chuàng)建的superuser賬戶和密碼登陸

利用Django框架編寫一個(gè)在線考試系統(tǒng)

進(jìn)入后臺

利用Django框架編寫一個(gè)在線考試系統(tǒng)

使用后臺添加學(xué)生信息

(6)實(shí)現(xiàn)學(xué)生的登陸
這里需要用到Django內(nèi)置的ORM模塊,不在贅述,需要的同學(xué)看前邊網(wǎng)站入門。

在views.py中創(chuàng)建studentLogin函數(shù)

學(xué)生登陸的form表單將學(xué)生輸入的學(xué)號(id),密碼(password)通過post方式提交給服務(wù)器,所以視圖函數(shù)先接受表單參數(shù),判斷用戶名和密碼與數(shù)據(jù)庫是否一致,若一致,則登陸成功。

登陸成功后,我需要發(fā)送至少三條信息給index.html,
(1)該學(xué)生的基本信息
(2)該學(xué)生考試信息,可通過該學(xué)生的專業(yè)名稱在試卷表中查到有哪些要進(jìn)行的考試
(3)該學(xué)生的考試成績信息,可通過學(xué)生的學(xué)號在paper表中查詢
代碼如下:

def studentLogin(request):
  if request.method=='POST':
    # 獲取表單信息
    stuId=request.POST.get('id')
    password=request.POST.get('password')
    print("id",stuId,"password",password)
    # 通過學(xué)號獲取該學(xué)生實(shí)體
    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)模板的渲染(數(shù)據(jù)的顯示)
登陸成功后,發(fā)送三個(gè)字典數(shù)據(jù)給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>
   <h4>考試信息</h4>
   <p></p>
    <table class="table">
  <thead>
   <tr>
     <th>學(xué)號</th>
    <th>姓名</th>
    <th>考試科目</th>
     <th>考試時(shí)間</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>
   <h4>考試成績</h4>
   <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>

利用Django框架編寫一個(gè)在線考試系統(tǒng)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

(8)教師登陸同上,學(xué)生在線考試和系統(tǒng)自動(dòng)閱卷怎么實(shí)現(xiàn)呢?我是這樣做的

學(xué)生登陸成功后,點(diǎn)擊"開始考試"按鈕,按鈕將兩個(gè)請求信息發(fā)送到服務(wù)器,自己的學(xué)號和試卷的科目。

startExam視圖函數(shù)接收到學(xué)號和試卷的科目,找到試卷信息發(fā)送給另一模板(exam.html)渲染
因此,建立繼續(xù)建立exam.html模板和startExam視圖函數(shù)

def startExam(request):
  sid = request.GET.get('sid')
  subject1=request.GET.get('subject')
  #得到學(xué)生信息
  student=models.Student.objects.get(id=sid)
  #試卷信息
  paper=models.Paper.objects.filter(subject=subject1)
  # print('學(xué)號',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>在線答題考試系統(tǒng)</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>
  <!--時(shí)間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"><h4>在線考試系統(tǒng)</h4></a>
    </li>

    <li class="nav-item active">
      <a class="nav-link"><h4>當(dāng)前科目:{{ subject }}</h4></a>
    </li>
    <li >{{ 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">&#xe6fb;</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">
								<h3>單選題</h3>
								<p>
									<span>共</span><i class="content_lit">10</i><span>題,</span>
                  <span>合計(jì)</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" >{{ test.optionA }}</p>
														</label>
													</li>

													<li class="option">
															<input type="radio" class="radioOrCheck" name="{{ test.id }}"
                              value="B"/>
														<label>
															B.<p class="ue" >{{ test.optionB }}</p>
														</label>
													</li>

													<li class="option">
															<input type="radio" class="radioOrCheck" name="{{ test.id }}"
                              value="C"/>
														<label>
															C.<p class="ue" >{{ test.optionC }}</p>
														</label>
													</li>

													<li class="option">
															<input type="radio" class="radioOrCheck" name="{{ test.id }}"
                              value="D"/>
														<label>
															D.<p class="ue" >{{ 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>

效果是這樣的:

利用Django框架編寫一個(gè)在線考試系統(tǒng)

自動(dòng)閱卷就簡單了:

  1. 學(xué)生提交自己的作答給服務(wù)器(同時(shí)發(fā)送自己的學(xué)號和考試科目)

  2. 服務(wù)器根據(jù)考試科目找到該試卷,并逐個(gè)比較學(xué)生作答和答案是否一致,若一致,則得到該題的分?jǐn)?shù),并累加學(xué)生成績

  3. 將學(xué)生的學(xué)號、該科成績、科目名稱作為一條記錄插入到grade表中,返回首頁

這里有個(gè)細(xì)節(jié),試卷中會(huì)有很多選擇題,后臺一次會(huì)接收到多個(gè)提交答案,我是這樣處理的,讓每個(gè)單選題(有4個(gè)選項(xiàng),使用同一name)的name屬性和該題在題庫表中的id 保持一致,這樣在獲取到題號后可以得到該題的答案,以便判斷是否作答正確,詳見exam.html。

計(jì)算成績的calGrade()視圖函數(shù)如下:

def calGrade(request):

  if request.method=='POST':
    # 得到學(xué)號和科目
    sid=request.POST.get('sid')
    subject1 = request.POST.get('subject')

    # 重新生成Student實(shí)例,Paper實(shí)例,Grade實(shí)例,名字和index中for的一致,可重復(fù)渲染
    student= models.Student.objects.get(id=sid)
    paper = models.Paper.objects.filter(major=student.major)
    grade = models.Grade.objects.filter(sid=student.id)

    # 計(jì)算該門考試的學(xué)生成績
    question= models.Paper.objects.filter(subject=subject1).values("pid").values('pid__id','pid__answer','pid__score')

    mygrade=0#初始化一個(gè)成績?yōu)?
    for p in question:
      qId=str(p['pid__id'])#int 轉(zhuǎn) string,通過pid找到題號
      myans=request.POST.get(qId)#通過 qid 得到學(xué)生關(guān)于該題的作答
      # print(myans)
      okans=p['pid__answer']#得到正確答案
      # print(okans)
      if myans==okans:#判斷學(xué)生作答與正確答案是否一致
        mygrade+=p['pid__score']#若一致,得到該題的分?jǐn)?shù),累加mygrade變量

    #向Grade表中插入數(shù)據(jù)
    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可視化數(shù)據(jù)
教師查看學(xué)生成績,可以統(tǒng)計(jì)各個(gè)分?jǐn)?shù)段的人數(shù)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

利用Django框架編寫一個(gè)在線考試系統(tǒng)

我的思路:

  1. 教師查看學(xué)生成績,點(diǎn)擊查看成績按鈕后,發(fā)送該科科目名稱給后臺后臺

  2. 視圖函數(shù)接收科目名,從grade表計(jì)算該科目各個(gè)分?jǐn)?shù)段的人數(shù),發(fā)送給前臺模板渲染,并可視化

視圖函數(shù)如下:

#教師查看成績
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})

上述內(nèi)容就是利用Django框架編寫一個(gè)在線考試系統(tǒng),你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI