Pythoner 的Flask项目实践-带折叠菜单的响应式多页面应用签到墙(源码)
文章目录
- 1,项目结构
- 2,app.py
- 3,导航栏页面模板home.html
- 4,其他页面
- 5,改装导航栏
在上一篇文章中的web应用 基础上,加上多个页面,通过路由跳转来访问不同页面。
1,项目结构
web_demo_flask/
│
├─ app.py
│
└─ templates/├─ home.html├─ about.html└─ contact.html
- 页面模板(放在 templates/ 文件夹下)
- 导航栏模板(home.html)
- app.py
2,app.py
改造后的 Flask 应用
from flask import Flask, render_template, request, redirect, url_forapp = Flask(__name__)# 内存中的签到列表
sign_in_list = []@app.route("/")
def home():"""首页"""return render_template("home.html")@app.route("/signwallet", methods=["GET", "POST"])
def signwallet():"""首页:签到表单 + 显示签到结果"""message = Noneif request.method == "POST":name = request.form.get("username", "").strip()if name:if name not in sign_in_list:sign_in_list.append(name)message = f"欢迎你,{name}!"else:message = "请输入名字再提交哦~"return render_template("signwallet.html", message=message, users=sign_in_list)@app.route("/about")
def about():"""关于页面"""return render_template("about.html")@app.route("/contact")
def contact():"""联系我们页面"""return render_template("contact.html")@app.route("/updatefeature")
def updatefeature():"""联系我们页面"""return render_template("updatefeature.html")@app.route("/terrain3D")
def terrain3D():"""联系我们页面"""return render_template("terrain3D.html")@app.route("/clear")
def clear():"""清空签到列表后跳回首页"""sign_in_list.clear()return redirect(url_for("home"))if __name__ == "__main__":app.run(debug=True, port=5000)
3,导航栏页面模板home.html
-
页面模板(放在 templates/ 文件夹下)
-
导航栏模板(home.html),让所有页面都能统一显示导航菜单
模板继承结构,增加一个统一的 导航栏模板 home.html,其他页面继承它,就能共享导航栏。
home.html(导航栏模板),放在 templates/ 文件夹下:
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>{% block title %}学习应用{% endblock %}</title><style>body {margin: 0;font-family: Arial, sans-serif;display: flex;height: 100vh;overflow: hidden;}/* 左侧导航栏 */.sidebar {width: 200px;background-color: #2c3e50;color: white;display: flex;flex-direction: column;padding: 20px 10px;}.sidebar h2 {margin: 0 0 20px;font-size: 18px;text-align: center;}.sidebar a {color: white;text-decoration: none;padding: 10px;margin-bottom: 5px;border-radius: 4px;display: block;}.sidebar a:hover {background-color: #34495e;}/* 主体内容区 */.content {flex: 1;background-color: #ecf0f1;padding: 20px;overflow-y: auto; /* ✅ 开启上下滚动 */}</style><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
</head>
<body><div class="sidebar"><h2>导航菜单</h2><a href="{{ url_for('home') }}">🏠 首页</a><a href="{{ url_for('signwallet') }}">ℹ️ 签名墙</a><a href="{{ url_for('updatefeature') }}">📞 地图实时更新</a><a href="{{ url_for('terrain3D') }}">📞 添加3D地图</a><a href="{{ url_for('about') }}"><i class="fa-solid fa-circle-info"></i> 关于</a><a href="{{ url_for('contact') }}"><i class="fa-solid fa-phone"></i> 联系我</a></div><div class="content">{% block content %}{% endblock %}</div>
</body>
</html>
把首页的 导航栏改成侧边栏(Side Navigation),并且在右侧主要内容区可以 上下滚动。
4,其他页面
所有页面(首页、关于、联系我们)都会自动带上统一的 导航栏。
修改 home.html 导航栏即可同步更新所有页面。
每个子页面只需专注写自己的内容,保持结构简洁。
contact.html
{% extends "home.html" %}{% block title %}联系我{% endblock %}{% block content %}
<!DOCTYPE html>
<html>
<head><title>联系我们</title>
</head>
<body><h1>联系信息</h1><p>邮箱:5758703@qq.com</p><p>微信:13930895264</p><p><a href="{{ url_for('home') }}">返回首页</a></p>
</body>
</html>
{% endblock %}
效果
- 左侧固定的 侧边导航栏,点击即可跳转不同页面。
- 右侧是 内容区域,支持上下滚动,即使内容很多也不会溢出。
- 简洁、清晰,结构和代码都比较轻量。
-
左侧导航栏固定,点击导航链接时,右侧 content 容器中的内容要跟随路由变化加载不同页面内容。
-
home.html 定义统一框架(左侧导航栏 + 右侧 content 容器)
-
每个页面(home、about、contact…)继承 base.html,把内容渲染到 content 容器中
-
Flask 的路由决定渲染哪个子页面
-
这样点击左侧导航链接时,Flask 会切换路由,重新渲染对应页面,但左侧导航栏始终保持不变。
-
就像一个简易的 后台管理系统框架
5,改装导航栏
把现在的 侧边栏导航栏 升级成:
-
折叠菜单(Accordion):可展开/收起子菜单
-
响应式:PC 上是侧边栏,手机上自动变成顶部菜单(汉堡按钮)
-
样式更现代化
这里我们用 Bootstrap 5来做,它直接提供了折叠和响应式导航组件。下面给出一个完整的home.html 示例:
✅ home.html (Bootstrap5 + Accordion + 响应式导航)
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>{% block title %}签到墙应用{% endblock %}</title><!-- 引入 Bootstrap5 CSS --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"><!-- 引入 Font Awesome 图标 --><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet"><style>body {display: flex;flex-direction: column;height: 100vh;margin: 0;}.main-content {flex: 1;display: flex;overflow: hidden;}.sidebar {width: 250px;background-color: #2c3e50;color: white;padding: 10px;}.sidebar a {color: white;text-decoration: none;padding: 6px 10px;border-radius: 4px;display: block;}.sidebar a.active, .sidebar a:hover {background-color: #1abc9c;color: white;}.content {flex: 1;padding: 20px;overflow-y: auto;background-color: #ecf0f1;}@media (max-width: 768px) {.sidebar { display: none; }}</style>
</head>
<body><!-- 移动端顶部导航 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark d-md-none"><div class="container-fluid"><a class="navbar-brand" href="#">签到墙</a><button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mobileNav"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="mobileNav"><ul class="navbar-nav"><li class="nav-item"><a class="nav-link {% if request.endpoint=='home' %}active{% endif %}" href="{{ url_for('home') }}"><i class="fa-solid fa-house"></i> 首页</a></li><li class="nav-item"><a class="nav-link {% if request.endpoint=='about' %}active{% endif %}" href="{{ url_for('about') }}"><i class="fa-solid fa-circle-info"></i> 关于</a></li><li class="nav-item"><a class="nav-link {% if request.endpoint=='contact' %}active{% endif %}" href="{{ url_for('contact') }}"><i class="fa-solid fa-phone"></i> 联系我们</a></li><li class="nav-item"><a class="nav-link {% if request.endpoint=='clear' %}active{% endif %}" href="{{ url_for('clear') }}"><i class="fa-solid fa-broom"></i> 清空签到</a></li></ul></div></div>
</nav><div class="main-content"><!-- 桌面端侧边栏 --><div class="sidebar d-none d-md-block"><h4 class="text-center">导航菜单</h4><div class="accordion accordion-flush" id="accordionMenu"><div class="accordion-item bg-transparent border-0"><h2 class="accordion-header"><button class="accordion-button collapsed bg-transparent text-white" type="button"data-bs-toggle="collapse" data-bs-target="#collapseOne"><i class="fa-solid fa-layer-group me-2"></i> 功能菜单</button></h2><div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionMenu"><div class="accordion-body"><a href="{{ url_for('home') }}" class="{% if request.endpoint=='home' %}active{% endif %}"><i class="fa-solid fa-house"></i> 首页</a><a href="{{ url_for('about') }}" class="{% if request.endpoint=='about' %}active{% endif %}"><i class="fa-solid fa-circle-info"></i> 关于</a></div></div></div><div class="accordion-item bg-transparent border-0"><h2 class="accordion-header"><button class="accordion-button collapsed bg-transparent text-white" type="button"data-bs-toggle="collapse" data-bs-target="#collapseTwo"><i class="fa-solid fa-gear me-2"></i> 系统操作</button></h2><div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionMenu"><div class="accordion-body"><a href="{{ url_for('contact') }}" class="{% if request.endpoint=='contact' %}active{% endif %}"><i class="fa-solid fa-phone"></i> 联系我们</a><a href="{{ url_for('clear') }}" class="{% if request.endpoint=='clear' %}active{% endif %}"><i class="fa-solid fa-broom"></i> 清空签到</a></div></div></div></div></div><!-- 右侧内容 --><div class="content">{% block content %}{% endblock %}</div>
</div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
- 高亮当前页面菜单项(active 状态)
- 当前访问的页面(home、about、contact、clear)对应的导航项会 高亮背景色;
- PC 端侧边栏 + 折叠菜单能看到高亮;
- 移动端顶部汉堡菜单展开时,也能看到高亮状态。
“人的一生会经历很多痛苦,但回头想想,都是传奇”。