本系列博文献系列文章共三篇,在编写的过程中可以说几乎是参照毕业设计目录样式来进行的.
相关图表和截图也都几乎按照毕业设计论文的要求来编制,完整阅读消化此系列博文套上一个毕业论文的目录和格式几乎就是一篇计算机毕业设计论文了.
本文是Python Web在线考试管理系统毕设第二篇,另外两篇如下:
- 基于Python Web的在线考试管理系统毕设之需求分析和数据库设计篇:基于Python Web的在线考试管理系统毕设之需求分析和数据库设计篇_高校在线考试系统毕设论文数据库设计-CSDN博客
- 基于Python Web的在线考试管理系统毕业设计之数据库及系统实现
- 基于Python Web的在线考试管理系统毕设之论文和源码篇
本文所需软件及系统环境请参见:[Python+Django]Web图书管理系统毕业设计之开发工具和技术篇:
基于Python Web的在线考试管理系统毕设之需求分析和数据库设计篇_高校在线考试系统毕设论文数据库设计-CSDN博客
本文我们完成数据的设计,并通过Django框架完成数据库构建同时利用Django框架模式实在线考试管理系统的功能。
简单的包装下毕设应该没问题了。
Python,Mysql,Pycharm的安装本文就不做特别介绍了,有需要的同学请参考如下博文。
Python + Django4 搭建个人博客(二):准备开发环境
最终实现系统功能结构如下
系统代码文件结构:
各模块功能页面
学生信息管理功能:
课程信息管理功能
数据库设计:
(1)用户表结构
根据前文定义的实体属性,我们完成课程表结构设计如表4-1
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每门课程的ID |
name | VARCHAR(255) | 名称 |
用户表结构表4-1
(2)学生表结构
学生实体与用户实体是1对1关系,可以通过外键形式和用户表进行关联。
根据前文概念设计和实体关系,设计学生表结构如表4-2。
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每个学生的ID |
User | INT (外键) | 与用户表关联,一对一关系,存储学生的用户信息ID |
name | VARCHAR(100) | 存储学生的姓名 |
gender | VARCHAR(10) | 存储学生的性别 |
birth_date | DATE | 存储学生的出生日期 |
phone_number | VARCHAR(20) | 存储学生的联系电话 |
address | VARCHAR(255) | 存储学生的居住地址 |
学生表结构表4-2
(3)课程表结构
根据前文定义的实体属性,我们完成课程表结构设计如表4-3
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每门课程的ID |
course_name | VARCHAR(255) | 存储课程的名称 |
description | TEXT | 存储课程的详细描述 |
credits | DECIMAL(5,2) | 存储课程的学分 |
hours | DECIMAL(5,2) | 存储课程的课时 |
课程表结构表4-3
(4)考试试卷表结构
试卷表和课程是一对多关系,一门课程可以有多次考试,在试卷表中以外键形式和课程表进行关联,根据概念结构和实体关系,完成试卷表结构设计如表4-4。
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每次考试的ID |
name | VARCHAR(255) | 存储考试试卷的名称 |
course | INT (外键) | 与课程表关联,外键关系,存储该考试所属的课程ID |
duration | INT | 存储考试的时长(以秒为单位) |
created_at | DATETIME | 自动记录创建时间 |
updated_at | DATETIME | 自动记录更新时间 |
试卷表结构表4-4
(5)题库(Question)表结构
题库用来存储试题的题干信息,通过外键形式与试卷进行关联,一个试卷可以有多个题库中的题目,结合前文的概念结构设计和实体关系,完成题库表结构设计如表4-5所示。
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每道试题的ID |
question_text | TEXT | 存储试题的题目内容 |
question_type | VARCHAR(20) | 存储试题的类型(如单选题、判断题等) |
exam | INT (外键) | 与考试表关联,外键关系,存储该试题所属的考试ID |
created_at | DATETIME | 自动记录创建时间 |
updated_at | DATETIME | 自动记录更新时间 |
题库表结构表4-5
(6)选项(Option)
选项表用来存储题库中题目的选项及答案信息,一个题目可以有多个选项,在选项表中通过外键形式和题库中题目信息关联,根据概念结构设计和关系描述,完成选项表结构设计如表4-6所示。
属性名称 | 数据类型 | 描述 |
ID | INT (主键,自增) | 唯一标识每个选项的ID |
question | INT (外键) | 与试题表关联,外键关系,存储该选项所属的试题ID |
text | TEXT | 存储选项的具体内容 |
is_correct | BOOLEAN | 标识该选项是否为正确答案 |
选项表结构表4-6
(7)学生分数(StudentScore)
属性名称 | 数据类型 | 描述 |
id | AutoField | 主键,自动增长 |
student | INT (外键) | 外键关联到Student模型,如果关联的Student被删除,则级联删除此记录 |
exam | INT (外键) | 外键关联到Exam模型,如果关联的Exam被删除,则级联删除此记录 |
score | DecimalField | 分数,最大5位数字,其中2位为小数,可以为空 |
completed_at | DateTimeField | 完成时间,可以为空 |
系统代码实现
大致理清了我们需要实现的功能模块之后,我们开始撸代码
1 、开发环境搭建及技术选型
服务端:Python 3.9
Web框架:Django 4
数据库:MySQL mysql-8.0.13-winx64
开发工具IDE:Pycharm
前端框架:Bootstrap 4
2、Django项目创建及数据库连接配置
2.1 Django项目创建
1.在任意盘符文件夹下新建一个空白Pycharm项目文件夹比如:PycharmProjects
2.打开Pycharm,进入空白文件夹:PycharmProjects
3.通过Pycharm 的Windows 命令行输入界面输入创建Django项目的命令,创建一个新的项目:django_exam_2024
django-admin startproject django_exam_2024
2.2、 数据库创建和连接配置
Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。
Django 为这些数据库提供了统一的调用API。
我们可以根据自己业务需求选择不同的数据库。
MySQL 是 Web 应用中最常用的数据库。
本文采用MySQL。
- 数据库创建
Django只能操作到数据表级别,不能操作到数据库级别,所以需要手工创建一个数据库:djangoexam2024
我们可以通过命令行创建一个数据库:
1.进入mysql安装文件夹的bin 子文件夹目录:
比如:D:\Program Files\mysql-8.0.13-winx64\bin
2.连接数据库:
mysql -u root -p Enter password:******
3.连接登录成功后通过命令创建一个数据库:djangoexam2024
CREATE DATABASE IF NOT EXISTS djangoexam2024 DEFAULT CHARSET utf8;
或者通过SQLlog工具创建一个数据库: djangoexam2024
- Django数据库连接配置
Django使用MySQL需要mysql 驱动,如果你没安装 mysql 驱动,可以执行以下命令安装:
pip install pymysql
安装好之后, 进入django_exam_2024
项目下的django_exam_2024
文件夹,打开setting.py 文件,找到DATABASES配置项,修改DATABSES配置项为如下内容:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'djangoexam2024', # 数据库名称
'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项目django_exam_2024
用于我们后续系统开发的程序编写。
同时为此项目创建了一个MySQL数据库:djangoexam2024
用于我们程序开发过程中的数据存放和处理。
3 功能模块详细开发
一个Django项目框架搭建起来后,我们所有对系统的前后台所有的程序开发都可以在这个项目中进行了,一个典型的Django项目模块功能的开发包括如下几个步骤:
- 创建,注册app
- 定义模型
- 定义视图函数
- 配置访问路由URL
- 静态资源准备及配置
- 前端模板开发
- 测试及运行
3.1 学生管理模块功能实现
3.1.1 创建App
在Django中的一个app代表一个功能模块,
本来一般实际开发中方便管理一个功能模块需要单独新建一个app,我们为了快速开发,所有的功能和模型都在一个app中进行管理。
在命令行中输入python manage.py startapp app01
指令,创建名为app01的app:
python manage.py startapp app01
在 django_exam_2024
文件夹目录下的settings.py 中找到INSTALLED_APPS配置项,将新创建的app01添加到项目的app列表,如下:
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01' #添加此项
]
3.1.2 定义模型
Django通过模型将程序中的字段和数据库对应起来,同时在程序和数据中间来传递数据。
Django 模型使用自带的 ORM。
我们之前创建了一个空白的数据库djangoexam2024
,这一步我们通过Django的模型来完成数据库表的创建.
因为Django对模型和目标数据库之间有自身的映射规则,如果自己在数据库中创建数据表,可能不一定符合Django的建表规则,从而导致模型和目标数据库无法建立通信联系。
所以最好我们在Django项目中还是通过Django模型来创建对应数据库表
一个表对应一个模型,本步骤按照我们前面数据库设计需要设计6个模型(Django自带User模型,所以我们可以不用自定义User模型):
打开django_exam_2024
/app01/models.py,建立6个模型:
from django.db import models
# Create your models here.
from django.contrib.auth.models import User
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
gender = models.CharField(max_length=10)
birth_date = models.DateField()
phone_number = models.CharField(max_length=20)
address = models.CharField(max_length=255)
def __str__(self):
return self.name
class Course(models.Model):
CourseName = models.CharField(max_length=255)
Description = models.TextField(blank=True)
# Teacher = models.CharField(max_length=255)
Credits = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return self.CourseName
# 试卷模型
class Exam(models.Model):
name = models.CharField(max_length=255, verbose_name='试卷名称')
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='course', verbose_name='课程')
duration = models.IntegerField(verbose_name='考试时长(秒)')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
def __str__(self):
return self.name
# 试题模型
class Question(models.Model):
question_text = models.TextField(verbose_name='题目内容')
question_type = models.CharField(max_length=20, choices=[('single_choice', '单选题'), ('judgment', '判断题')],
verbose_name='试题类型')
exam = models.ForeignKey(Exam, on_delete=models.CASCADE, related_name='questions', verbose_name='所属试卷')
score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True, verbose_name='分值')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
def __str__(self):
return self.question_text[:50] # 返回题目内容的前50个字符,避免过长
def get_options(self):
return self.options.all()
def get_correct_option(self):
# 获取当前问题的正确选项
try:
correct_option = self.options.get(is_correct=True)
return correct_option
except Option.DoesNotExist:
return None
# 试题选项模型
class Option(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='options', verbose_name='所属试题')
option_text = models.CharField(max_length=255, verbose_name='选项内容')
is_correct = models.BooleanField(default=False, verbose_name='是否为正确答案')
created_at = models.DateTimeField(auto_now=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
def __str__(self):
return self.option_text
# 学生成绩模型
class StudentScore(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='scores', verbose_name='学生')
exam = models.ForeignKey(Exam, on_delete=models.CASCADE, related_name='exam_scores', verbose_name='所属试卷')
score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True, verbose_name='分数')
completed_at = models.DateTimeField(null=True, blank=True, verbose_name='完成时间')
class Meta:
unique_together = (('student', 'exam'),) # 每个学生在同一张试卷上只能有一条成绩记录
def __str__(self):
return f"{self.student.user.username} - {self.exam.name} - {self.score}" if self.score else f"{self.student.name} - {self.exam.name} - 未完成"
编写好了Model后,接下来就需要进行数据迁移。迁移是Django对模型所做的更改传递到数据库中的方式。
注意,每当对数据库进行了更改(添加、修改、删除等)操作,都需要进行数据迁移。
Django的迁移代码是由模型文件自动生成的,它本质上只是个历史记录,Django可以用它来进行数据库的滚动更新,通过这种方式使其能够和当前的模型匹配。
在命令行中输入命令让 Django知道我们自定义模型有一些变更,并根据我们自定义app的模型生成创建数据表的脚本:
python manage.py makemigrations
最后通过命令创建app模型对应的数据库表:
python manage.py migrate
3.1.3 定义视图函数
Django 中视图的概念是「一类具有相同功能和模板的网页的集合」。
比如,在一个考试系统中,我们可能需要如下几个视图:
登录:输入用户和密码,根据校验结果进行登录处理。
考试:展示考试试题及选项,根据选择的结果记录考试成绩。
这些需求都靠视图(View)来完成。
每一个视图表现为一个简单的Python函数,它需要要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse对象,或者抛出一个异常,比如 Http404 。
视图函数中的request与网页发来的请求有关,里面包含get或post的内容、用户浏览器、系统等信息。
根据系统设计过程中需要的功能,我们在app01/views.py
文件中创建4个视图函数分别实现学生信息的增删改查。
def student_list(request):
students = Student.objects.all()
return render(request, 'student_list.html', {'students': students})
@login_required
def student_update(request, pk):
student = get_object_or_404(Student, pk=pk)
if request.method == 'POST':
# 更新学生信息
student.name = request.POST.get('name')
student.gender = request.POST.get('gender')
student.birth_date = request.POST.get('birth_date')
student.phone_number = request.POST.get('phone_number')
student.address = request.POST.get('address')
student.save()
return redirect('student_list') # 重定向到学生列表页面
return render(request, 'student_update.html', {'student': student})
@login_required
def create_student(request):
if request.method == 'POST':
# 获取POST数据
username = request.POST.get('username')
password = request.POST.get('password')
name = request.POST.get('name')
gender = request.POST.get('gender')
birth_date = request.POST.get('birth_date') # 注意:这里可能需要转换为日期对象
phone_number = request.POST.get('phone_number')
address = request.POST.get('address')
# 尝试创建User对象
try:
user = User.objects.create_user(username=username, password=password)
# 创建Student对象并与User关联
Student.objects.create(user=user, name=name, gender=gender, birth_date=birth_date,
phone_number=phone_number, address=address)
return redirect('student_list')
except Exception as e:
return render(request, 'register.html')
# 如果是GET请求,直接渲染注册页面
return render(request, 'create_student.html')
@login_required
def student_delete(request, pk):
student = get_object_or_404(Student, pk=pk)
if request.method == 'POST':
student.delete()
return redirect('student_list') # 重定向到学生列表页面
return render(request, 'student_delete.html', {'student': student})
3.1.4 模板创建
Django作为Web框架,需要一种很便利的方法去动态地生成HTML网页,因此有了模板这个概念。
模板包含所需HTML的部分代码以及一些特殊的语法,特殊的语法用于描述如何将数据动态插入HTML网页中。
在开始模板创建之前我们需要简单配置下。
先在根目录django_exam_2024
下新建一个文件夹templates
用于存放我们的所有的模板文件。
模板位置也同样需要在配置文件中指定模板的存放位置,在..\django_exam_2024\django_exam_2024\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',
],
},
},
]
完成文件夹创建和配置之后,我们可以开始模板创建了。
首先我们在模板文件中新建如下3个文件:
base.html
:是整个项目的模板基础,所有的网页都从它继承;header.html
:是网页顶部的导航栏;footer.html
:是网页底部的注脚;
上述三个文件是网站页面的通用组件模块,基本上每个页面都不会变,所以我们把他们独立出来。
我们编写Django后续的页面模板时可以直接继承对应的通用模板组件。
分别编写三个静态HTML文件代码如下:
templates/base.html:
<!-- 载入静态文件-->
{% load static %}
<!-- 网站主语言 -->
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block title %}{% endblock title %}
<link href="https://cdn.staticfile.net/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.net/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<!-- 引入导航栏 -->
{% include 'header.html' %}
<!-- 预留具体页面的位置 -->
{% block content %}{% endblock content %}
<!-- 引入注脚 -->
{% include 'footer.html' %}
</body>
</html>
templates/header.html:
<!-- 导航栏 -->
<!-- 定义导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<!-- 导航栏商标 -->
<a class="navbar-brand" href="/index">在线考试管理系统</a>
<!-- 导航入口 -->
<div>
<ul class="navbar-nav">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="/index">在线考试</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/score_list">成绩管理</a>
</li>
{% if user.is_superuser %}
<li class="nav-item">
<a class="nav-link" href="/student_list/">学生管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/course_list">课程管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/question_list">题库管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/option_list">选项管理</a>
</li>
{% endif %}
{% endif %}
<!-- Django的 if 模板语句 -->
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
data-bs-toggle="dropdown" aria-expanded="false">
{{ user.username }}
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="/profile">个人信息</a></li>
<li><a class="dropdown-item" href="/logout">退出登录</a></li>
</ul>
</li>
<!-- 如果用户未登录,则显示 “登录” -->
{% else %}
<li class="nav-item">
<a class="nav-link" href="/login">登录</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"></p>
</div>
</footer>
接下来我们就来实现详细各个视图函数对应的网页模板了
前文定义视图的时候指定了学生信息增删改查的模板如下:student_list.html
,create_student.html
,student_delete.html
,student_update.html
。
下面我们分别创建4个模板:
学生添加:templates/create_student.html
<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load static %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
<title>创建学生</title>
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h1 class="mb-5">创建学生</h1>
<form action="{% url 'create_student' %}" method="post" class="needs-validation" novalidate>
{% csrf_token %}
<div class="row g-3">
<div class="col-md-6">
<label for="username" class="form-label">用户名:</label>
<input type="text" class="form-control" id="username" name="username" required>
<div class="invalid-feedback">
请输入用户名。
</div>
</div>
<div class="col-md-6">
<label for="password" class="form-label">密码:</label>
<input type="password" class="form-control" id="password" name="password" required>
<div class="invalid-feedback">
请输入密码。
</div>
</div>
<div class="col-md-6">
<label for="name" class="form-label">姓名:</label>
<input type="text" class="form-control" id="name" name="name" required>
<div class="invalid-feedback">
请输入姓名。
</div>
</div>
<div class="col-md-6">
<label for="gender" class="form-label">性别:</label>
<select class="form-select" id="gender" name="gender" required>
<option value="" disabled selected>请选择性别</option>
<option value="male">男</option>
<option value="female">女</option>
</select>
<div class="invalid-feedback">
请选择性别。
</div>
</div>
<div class="col-md-6">
<label for="birth_date" class="form-label">出生日期:</label>
<input type="date" class="form-control" id="birth_date" name="birth_date" required>
<div class="invalid-feedback">
请选择出生日期。
</div>
</div>
<div class="col-md-6">
<label for="phone_number" class="form-label">电话号码:</label>
<input type="tel" class="form-control" id="phone_number" name="phone_number" required>
<div class="invalid-feedback">
请输入电话号码。
</div>
</div>
<div class="col-md-12">
<label for="address" class="form-label">地址:</label>
<textarea class="form-control" id="address" name="address" rows="3" required></textarea>
<div class="invalid-feedback">
请输入地址。
</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">创建学生</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock content %}
学生编辑:templates/student_update.html
<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load static %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
<title>创建课程</title>
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<div class="container mt-5">
<h1>编辑学生信息</h1>
<form method="post" class="row g-3">
{% csrf_token %}
<input type="hidden" name="pk" value="{{ student.pk }}">
<div class="col-md-6">
<label for="id_name" class="form-label">姓名:</label>
<input type="text" id="id_name" name="name" value="{{ student.name }}" class="form-control" required>
</div>
<div class="col-md-6">
<label for="id_gender" class="form-label">性别:</label>
<select id="id_gender" name="gender" class="form-select" required>
<option value="male" {% if student.gender == 'male' %}selected{% endif %}>男</option>
<option value="female" {% if student.gender == 'female' %}selected{% endif %}>女</option>
<option value="other" {% if student.gender == 'other' %}selected{% endif %}>其他</option>
<!-- 添加其他选项... -->
</select>
</div>
<div class="col-md-6">
<label for="id_birth_date" class="form-label">出生日期:</label>
<input type="date" id="id_birth_date" name="birth_date" value="{{ student.birth_date|date:'Y-m-d' }}"
class="form-control" required>
</div>
<div class="col-md-6">
<label for="id_phone_number" class="form-label">电话号码:</label>
<input type="text" id="id_phone_number" name="phone_number" value="{{ student.phone_number }}"
class="form-control" required>
</div>
<div class="col-12">
<label for="id_address" class="form-label">地址:</label>
<textarea id="id_address" name="address" rows="4" class="form-control"
required>{{ student.address }}</textarea>
</div>
<!-- 添加提交按钮 -->
<div class="col-12">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
<!--<div class="container">-->
<!-- <div class="row">-->
<!-- <!– 主体内容区域 –>-->
<!-- <div class="container mt-5">-->
<!-- <h1>编辑学生信息</h1>-->
<!-- <form method="post">-->
<!-- {% csrf_token %}-->
<!-- <input type="hidden" name="pk" value="{{ student.pk }}">-->
<!-- <div>-->
<!-- <label for="id_name">姓名:</label>-->
<!-- <input type="text" id="id_name" name="name" value="{{ student.name }}" required>-->
<!-- </div>-->
<!-- <div>-->
<!-- <label for="id_birth_date">出生日期:</label>-->
<!-- <input type="date" id="id_birth_date" name="birth_date"-->
<!-- value="{{ student.birth_date|date:'Y-m-d' }}" required>-->
<!-- </div>-->
<!-- <div>-->
<!-- <label for="id_phone_number">电话号码:</label>-->
<!-- <input type="text" id="id_phone_number" name="phone_number" value="{{ student.phone_number }}"-->
<!-- required>-->
<!-- </div>-->
<!-- <div>-->
<!-- <label for="id_address">地址:</label>-->
<!-- <textarea id="id_address" name="address" required>{{ student.address }}</textarea>-->
<!-- </div>-->
<!-- <button type="submit">更新</button>-->
<!-- </form>-->
<!-- </div>-->
<!-- </div>-->
<!--</div>-->
{% endblock content %}
学生列表:templates/student_list.html
<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load static %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
<title>创建课程</title>
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<div class="container">
<div class="row">
<!-- 主体内容区域 -->
<div class="container mt-5">
<!-- 学生列表标题 -->
<h1>学生列表</h1>
<div class="d-flex justify-content-end mb-3">
<a href="{% url 'create_student' %}" class="btn btn-primary">新增学生</a>
</div>
<!-- 学生表格 -->
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>性别</th>
<th>出生日期</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr>
<td>{{ student.id }}</td>
<td>{{ student.name }}</td>
<!-- <td>{{ student.gender }}</td>-->
<td>{% if student.gender == 'male' %}男{% else %}女{% endif %}</td>
<td>{{ student.birth_date|date:"Y-m-d" }}</td>
<td>
<!-- 添加编辑和删除链接(或其他操作) -->
<a href="{% url 'student_update' student.id %}">编辑</a>
<a href="{% url 'student_delete' student.id %}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
学生删除:templates/student_delete.html
<h1>删除学生信息</h1>
<p>你确定要删除学生 {{ student.name }} 吗?</p>
<form method="post">
{% csrf_token %}
<input type="hidden" name="pk" value="{{ student.pk }}">
<button type="submit">删除</button>
</form>
3.1.5 配置访问路由URL
有了视图和模板后,我们还需要将视图函数和模板(Web网页)链接对应起来。
url可以理解为访问网站时输入的网址链接,配置好url后Django才知道怎样定位app。
打开django_exam_2024/urls.py
,输入如下代码:
from django.contrib import admin
from django.urls import path , re_path
from app01 import views
urlpatterns = [
path('student_list/', views.student_list, name='student_list'),
path('student_update/<int:pk>', views.student_update, name='student_update'),
path('student_delete/<int:pk>', views.student_delete, name='student_delete'),
path('create_student/', views.create_student, name='create_student'),
]
通过配置如上URL,Django 将会根据用户请求的 URL 来选择使用哪个视图。
3.1.6 测试及运行
至此,我们已经在Django项目文件夹下创建了一个app:app01来管理我们的视图功能。
同时通过URL将视图和网页进行了数据的关联和展示。
在Windows命令行输入:
python manage.py runserver
运行服务器后在浏览器中输入我们之前配置的URL地址:
测试页面展示如下:
学生添加:
http://127.0.0.1:8000/create_student.html
学生编辑:
http://127.0.0.1:8000/student_update.html
学生列表:
http://127.0.0.1:8000/student_list.html
学生删除:
http://127.0.0.1:8000/student_delete.html