Flask + Bootstrap · 精讲
1. 环境准备
- 检查Python版本:python --version 或 python3 --version
- 创建项目目录:mkdir flask-bootstrap-project 然后 cd flask-bootstrap-project
2. 虚拟环境
- 创建:python3 -m venv .venv (Windows) / python3 -m venv venv (Mac/Linux)
- 激活:
- Windows CMD: .venv\Scripts\activate
3. 安装 Flask
- 升级pip(可选):python -m pip install --upgrade pip
- 安装Flask:pip install 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' %}