Flask + Bootstrap · 精讲 2026-09-08

1. 环境准备

2. 虚拟环境

3. 安装 Flask

4. 创建app.py 里面初始代码

print("脚本已启动") # 放在 import 之前 from flask import Flask, render_template, request import db app = Flask(__name__) # __name__ 当前模块 @app.route('/') def hello(): return render_template('flbootstrap.html') if __name__ == '__main__': app.run(debug=True)

5. 引入 Bootstrap (CDN),直接复制运行即可 终端python app.py

<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> <h1>Hello, world! hahhah</h1> <button type="button" class="btn btn-dark">Dark</button> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-7ymO4nGrkm372HoSbq1OY2DP4pEZnMiA+E0F3zPr+JQQtQ82gQ1HPY3QIVtztVua" crossorigin="anonymous"></script> </body> </html>

6. 上面的代码拆分 head.html / foot.html

将 <body> 以上放入 head.html,<body> 以下放入 foot.html,中间用 {% include %} 引入。
flbootstrap.html {% include 'head.html' %} <h1>Hello, world! 已拆分head和foot</h1> <button type="button" class="btn btn-dark">Dark</button> {% include 'foot.html' %}

7. 导航栏 · 放在 head.html,因为每个页面都要有

<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <a class="navbar-brand" href="#">成绩管理</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="/flluru.html">成绩录入</a> </li> <li class="nav-item"> <a class="nav-link" href="/flzhanshi.html">成绩展示</a> </li> </ul> {% if "user_name" not in session %} <a class="nav-link" href="/login">登录</a> {% else %} <a class="nav-link" href="/logout">退出</a> {% endif %} </div> </nav>

8. 登录页面 fldenglu.html

{% include 'head.html' %} <div class="container"> <h1>欢迎登录</h1> <form action="/fldenglu" method="post"> <div class="form-group"> <label for="exampleInputEmail1">Email address</label> <input type="email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"> <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small> </div> <div class="form-group"> <label for="exampleInputPassword1">Password</label> <input type="text" name="password" class="form-control" id="exampleInputPassword1"> </div> <div class="form-group form-check"> <input type="checkbox" class="form-check-input" id="exampleCheck1"> <label class="form-check-label" for="exampleCheck1">Check me out</label> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> {% include 'foot.html' %}

9. app.py 关于登录页面对应的函数

app.config["SECRET_KEY"] = 'sdafasfsafsafd' @app.route('/fldenglu', methods=['POST','GET']) def fldenglu(): if request.method == "POST": user_name = request.form.get("email") password = request.form.get("password") if user_name == "18435992007@163.com" and password == "bsj1011521": session["user_name"] = "admin" return redirect(url_for("flbootstrap")) return render_template('fldenglu.html') @app.route('/out') def out(): session.pop("user_name") return redirect(url_for("flbootstrap"))

10. 成绩展示 flzhanshi.html

{% include 'head.html' %} <div class="container"> <div class="jumbotron"> <h1>如下是学生成绩表</h1> </div> {{ table_html | safe }} </div> {% include 'foot.html' %}
@app.route("/flzhanshi") def flzhanshi(): if "user_name" not in session: return redirect(url_for("flbootstrap")) df = pd.read_excel("学生成绩表.xlsx") return render_template("flzhanshi.html", table_html=df.to_html(classes="table table-hover table-sm"))

11. 成绩录入 flluru.html

{% include 'head.html' %} <div class="container"> <div class="jumbotron"> <h1>请录入成绩</h1> <form action="/flluru" method="post"> <div class="form-group"> <label for="exampleInputName">请输入姓名</label> <input type="text" name="name" class="form-control" id="exampleInputName" aria-describedby="nameHelp"> <small id="nameHelp" class="form-text text-muted">请输入学生的姓名</small> </div> <div class="form-group"> <label for="exampleInputYuwen">语文成绩</label> <input type="text" name="yuwen" class="form-control" id="exampleInputYuwen"> </div> <div class="form-group"> <label for="exampleInputShuxue">数学成绩</label> <input type="text" name="shuxue" class="form-control" id="exampleInputShuxue"> </div> <div class="form-group"> <label for="exampleInputYingyu">英语成绩</label> <input type="text" name="yingyu" class="form-control" id="exampleInputYingyu"> </div> <button type="submit" class="btn btn-primary">提交</button> </form> </div> </div> {% include 'foot.html' %}

12.app.py 关于成绩录入页面对应的函数

@app.route("/flluru", methods=["POST", "GET"]) def submit_grade(): if "user_name" not in session: return redirect(url_for("flbootstrap")) if request.method == "POST": name = request.form.get("name") yuwen = request.form.get("yuwen") shuxue = request.form.get("shuxue") yingyu = request.form.get("yingyu") df = pd.read_excel("学生成绩表.xlsx") new_row = pd.DataFrame({ "姓名" : [name], "语文成绩" : [yuwen], "数学成绩" : [shuxue], "英语成绩" : [yingyu], }) df = pd.concat([new_row, df]) df.to_excel("学生成绩表.xlsx", index=False) return redirect(url_for("flzhanshi")) return render_template("flluru.html")

13. 巨幕效果 · 以及flbootstrap.html 最终效果

{% include 'head.html' %} <div class="jumbotron"> {% if "user_name" not in session %} <h1>欢迎来到成绩管理系统,请登录后使用</h1> {% else %} <h1>欢迎来到成绩管理系统,已登陆,用户名是{{ session["user_name"] }}</h1> {% endif %} </div> {% include 'foot.html' %}