Skip to main content

5.让班级列表页面真正成为页面

我们已经完成了班级管理的列表页:

  • 能访问
  • 能从数据库读数据
  • 页面不会报错

功能角度来说,这一页已经是合格的。

我猜你心中可能会有这样的疑问:

“功能虽然已经能跑了,但页面这么丑,正常吗?”

image-20251230172344132

如果你现在正有这种感觉,先别急。我可以很负责任地告诉你一句话:

非常正常,而且这是每一个 Web 开发者都会经历的阶段。

你现在处在的,正是从「能用」走向「像产品」的那一步。

那我们这一节到底要解决什么问题?

先别急着写代码,我们先明确目标。

这一节我们只做一件事:

让班级列表页面,具备一个真实管理系统该有的页面结构。

具体来说,我们要解决 3 个新手最容易卡住的问题:

  1. 如何来美化页面?
  2. 多个页面重复的结构,难道要每个都写一遍?
  3. 表格里的数据,怎么从“写死”变成“跟着数据库变”?

只要这三个问题你能走通, 后面的老师管理、学生管理、成绩管理,都会顺理成章。

第一步:别急着改逻辑,先把“静态页面”跑起来

通常我们说的Web开发包括前端+后端。在我们的项目中,Django输入后端开发语言。而前端开发这里我们使用最传统的三剑客:HTML+CSS+JavaScript.

想要把前面的班级列表页美化成下面的样式,那么就需要CSS(层叠样式表)。

image-20251231141422886

本套教程我们重点介绍的是后端Django框架,所以前端页面布局和样式就不带领大家一步一步来编写。这里为大家准备了本项目的前端静态页,如下图。

image-20251231142344642

所谓静态页,是指网页内容是固定不变的。你可以直接用浏览器打开静态页中的grades_list.html文件,查看班级列表的页面效果。

接下来,我们直接把静态页grades_list.html中代码,全部粘贴到项目文件中 grades_list.html。如下图。

image-20251231143015416

这一步你不需要理解每一行代码, 你只需要做一件事:刷新页面,看效果。

如果你发现:

  • 结构出来了
  • 但样式完全不对

别慌,这一步几乎 100% 都会这样。

image-20251231142859407

为什么页面“有结构却没样式”?

我当年第一次看到这种情况时,第一反应是:

“是不是我模板写错了?”

其实根本不是。

真正的原因只有一个:

CSS、JS、图片这些静态资源,还没有被 Django 正确加载。

第二步:把静态资源“安顿好”

在 Django 项目里,有一个非常明确的约定:

所有静态资源,都放在 static 目录下。

所以我们先什么都不想,按规矩来。

创建静态资源目录结构

static/
├── css/
├── js/
├── images/
└── fonts/

然后把对应的文件全部拷贝进去。如下图。

image-20251231143217745

第三步:用 Django 的方式加载静态资源

接下来,打开templates/grades/grades_list.html文件, 发现如下CSS文件。

  <link rel="stylesheet" href="static/css/base.css">
<link rel="stylesheet" href="static/css/index.css">
<link rel="stylesheet" href="static/css/iconfont.css">
<link rel="stylesheet" href="static/css/sweetalert2.css">
<script src="static/js/sweetalert2.js" ></script>

按照如下步骤进行修改:

1️⃣ 在模板顶部加载 static

`{% load static %}`

2️⃣ 使用 static 标签

`{% load static %}`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大熊课堂校园管理系统</title>

<link rel="stylesheet" href="`{% static 'css/base.css' %}`">
<link rel="stylesheet" href="{% static 'css/index.css' %}">
<link rel="stylesheet" href="{% static 'css/iconfont.css' %}">
<link rel="stylesheet" href="{% static 'css/sweetalert2.css' %}">
<script src="{% static 'js/sweetalert2.js' %}"></script>

</head>

【代码解析】

  • {% load static %} : 加载 staticfiles 应用提供的 static 模板标签,这样后续才能使用 {% static ... %} 来正确生成静态资源的 URL。

  • {% static 'css/base.css' %} 等价于 “/static/css/base.css”.

你现在可能还体会不到差别, 但等你将来部署项目、换环境、上服务器时——这一点,会帮你省掉大量无意义的坑。

【注意】检查settings.py文件中是否配置了STATICFILED_DIRS, 如下图。

image-20251231144701780

一切都准备就绪,请刷新页面,检查页面是否和静态页效果一样。如果依然没有显示样式,那么很可能是因为浏览器有缓存,清除浏览器历史记录重新尝试。

设置页面结构

现在我们来看页面结构。

你会发现:

  • 班级管理
  • 老师管理
  • 学生管理
  • 成绩管理

左侧边栏永远不变。

image-20251230165630035

这时候你应该在心里冒出一个问题:

“难道我要在每个页面里都复制一遍侧边栏吗?”

如果你这么做了,未来一定会后悔。

第四步:把“不会变的部分”变成父模板

我的经验是:

只要一个东西在多个页面出现,它就不应该写多次。

创建父模板 base.html

templates/
└── base.html
└── grades
└── grades_list.html

在这个文件中放入:

  • HTML 基本结构
  • CSS / JS 引入
  • 左侧边栏

而中间会变化的部分,用一个占位:

{% block content %}
{% endblock %}

base.html完整代码如下:

`{% load static %}`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大熊课堂校园管理系统</title>

<link rel="stylesheet" href="`{% static 'css/base.css' %}`">
<link rel="stylesheet" href="{% static 'css/index.css' %}">
<link rel="stylesheet" href="{% static 'css/iconfont.css' %}">
<link rel="stylesheet" href="{% static 'css/sweetalert2.css' %}">
<script src="{% static 'js/sweetalert2.js' %}"></script>
</head>
<body>
<div class="wrapper">
<div class="left">
<div class="head">
<a href="/students/">
<h2>学生管理系统</h2>
</a>
</div>
<div class="profile">
欢迎 [ admin ]
管理员
</div>
<div class="content">
<ul>
<li class="active">
<span class="iconfont icon-fangzi"></span>
<a href="/grades/" class="nav-link">班级管理</a>
</li>
<li>
<span class="iconfont icon-kapian"></span>
<a href="/teachers/">老师管理</a>
</li>
<li>
<span class="iconfont icon-ren"></span>
<a href="/students/">学生管理</a>
</li>
<li>
<span class="iconfont icon-shuben"></span>
<a href="/scores/">成绩管理</a>
</li>
<li>
<span class="iconfont icon-bianji"></span>
<a href="/change_password/">修改密码</a>
</li>
<li>
<span class="iconfont icon-shangchuan"></span>
<a href="/logout/">退出登录</a>
</li>
</ul>
</div>
</div>
<!-- 左侧结束 -->

{% block content %}
{% endblock %}
</div>
</body>
</html>

第五步:让班级列表页面“站在父模板肩膀上”

回到 grades_list.html,你只需要做两件事:

1️⃣ 继承父模板

{% extends 'base.html' %}

2️⃣ 填充自己的内容

{% block content %}
<!-- 班级列表相关内容 -->
{% endblock %}

刷新页面。

如果效果和之前一模一样,那说明你做对了。

页面没变,但结构已经彻底升级。


最后一步:把“写死的表格”交给数据库

现在再看表格内容。

如果你看到的是:

  • 固定的班级名称
  • 固定的班级编号

那说明它还不是“真正的管理系统”。

使用 for 循环遍历数据

`{% for grade in grades %}`
<tr>
<td>{{ grade.grade_name }}</td>
<td>{{ grade.grade_number }}</td>
<td>
<a href="#">编辑</a>
<a href="#">删除</a>
</td>
</tr>
`{% endfor %}`

这里的 grades,并不是凭空出现的。

它正是我们在 ListView 中配置的:

context_object_name = 'grades'

你不需要关心 SQL, 也不需要手动查询。

数据变,页面就跟着变。

image-20251231152031342

grades_list.html完整代码如下:

{% extends 'base.html' %}

{% block content %}
<div class="right">
<div class="top">
<div class="tool">
<div class="class-info">
<form method="get" action="/grades/">
<span>班级名称:</span>
<input type="text" name="search" placeholder="搜索班级名称..." value="">
<input type="submit" value="搜索">
<a href="#">
<button type="button" class="add">新增</button>
</a>
</form>
</div>
</div>
</div>
<div class="bottom">
<table>
<thead>
<tr>
<th>班级名称</th>
<th>班级编号</th>
<th>操作</th>
</tr>
</thead>
<tbody>
`{% for grade in grades %}`
<tr>
<td>{{ grade.grade_name }}</td>
<td>{{ grade.grade_number }}</td>
<td>
<a href="#">
<button class="add">编辑</button>
</a>
<a href="#">
<button class="del">删除</button>
</a>
</td>
</tr>
`{% endfor %}`
</tbody>
</table>

<!-- 分页导航 -->
<div class="pagination">
<span class="step-links">
<span class="current">
1 / 1
</span>
</span>
</div>
</div>
</div>
{% endblock %}

小结

如果你完整走通了这一节,其实已经说明一件事:

  • 你理解了模板继承
  • 你掌握了静态资源管理
  • 你已经在用“工程化思维”写 Django

下一节,我们会在这个基础上继续推进:

  • 搜索功能是如何实现的
  • 分页是如何接进来的
  • 一个完整 CRUD 是如何闭环的

你现在做的,已经不是“学 Django”, 而是在一步步搭一个真正的 Web 应用

但是请别忘记:动手写代码(Get Your Hands Dirty)