希望你已经看完了这个视频并自己动手做过一遍了。
web版学生信息后台管理系统(Python+flask框架+Bootstrap5)期末毕设必备_哔哩哔哩_bilibili
如果没有,我诚挚的建议你去看完再回来。
由于我做的时候没有留基础版,所以代码都是进阶版,但是进阶主要都在外观上,所以对功能没什么影响,应该也不影响理解,因为大多都是模板。除了我做的“高级功能聚合查找”。后面会讲到。
接下来我会把增删改查部分的函数如何改用mongodb操作完成讲掉,至于更高级的功能改进(比如登录验证之类的)我比较懒的去讲,我会直接发代码,也懒得再水几篇了。看不懂就自己学,学不会可以评论区答疑。
后端出现的主要函数说明:(可以先不看)
函数名 | 功能 |
render_template | 渲染网页 |
redirect | 对网页重定向,跳转至另一个网页 |
flask的POST和GET方法 | 分别向网页传参收参 |
collection.count_documents | 调用了mongo的数据库函数,清点数据库中符合条件的数据个数 |
collection.find_one | 调用了mongo的数据库函数,查找符合条件的一条数据 |
前端出现的主要函数说明:(可以先不看)
函数名或控制字段 | 功能 |
class | 控制内容类 |
page-header | 作为标题 |
text-center | 内容居中 |
text-primary | 内容呈现蓝色 |
style | 控制风格 |
margin | 控制边缘 |
<h1> | 最大字号标题 |
style="background-image: | 控制背景图片 |
background-size: cover; | 背景图片大小:覆盖全网页 |
alt | 若图片无法正常加载则显示其他内容 |
class="form-floating" | 启用浮动标签 |
style="width:400px; | 控制宽度 |
placeholder | 占位符,服务于浮动标签 |
button | 控制按钮 |
href | 超链接跳转至 |
1、Admin界面
2管理员登陆界面
前端代码:
@app.route('/admin')
def admin():
# 重新传一遍数据库
users = collection.find({}, {'_id': 0})
return render_template('admin.html', users=users)
函数名 | 功能 |
collection.find({}, {'_id': 0}) | 调用了mongo的数据库函数,传回数据库全部数据,删去_id字段 |
后端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<div class="page-header text-center text-primary"
style="margin: 10px auto">
<h1>
运营商信息管理系统
</h1>
</div>
<title>管理员登录</title>
<link rel="stylesheet" href="/static/css/bootstrap.css">
</head>
<body style="background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1111%2F02141Q60635%2F1P214160635-6.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1653756313&t=307537ded5422841d9bbff1e4a1b1e7f');
background-size: cover;">
<div class="container" style="width: auto;margin: auto auto">
<div class="row">
<div class="col-4">
<a class="btn btn-primary" href="/add">新增用户信息</a>
<a class="btn btn-primary" href="/search">查找</a>
</div>
</div>
</div>
<table class="table table-striped" style="width: auto;margin: auto auto">
<thead>
<tr>
<th scope="col">电话号码</th>
<th scope="col">姓名</th>
<th scope="col">密码</th>
<th scope="col">身份证号</th>
<th scope="col">是否管理员</th>
<th scope="col">¥话费余额</th>
<th scope="col">¥本期应付</th>
<th scope="col">¥月基本费</th>
<th scope="col">¥套餐外费用</th>
<th scope="col">套餐含语音通话/min</th>
<th scope="col">套餐含流量/GB</th>
<th scope="col">语音通话总时长/min</th>
<th scope="col">流量已使用/GB</th>
<th scope="col">是否开通VPN</th>
<th scope="col">超出语音/min</th>
<th scope="col">超出流量/GB</th>
</tr>
</thead>
<tbody>
{#需要将python的对象数据显示到浏览器上,模板语法
比较出名的是jinjia2
#}
{# 从数组中取出数据,slice切片,for循环 #}
{# 用法{{ users }} #}
{% for user in users %}
<tr>
<th>{{ user.phone }}</th>
<th>{{ user.name }}</th>
<th>{{ user.password }}</th>
<th>{{ user.IDnum }}</th>
<th>{{ user.ADMIN }}</th>
<th>{{ user.balance }}</th>
<th>{{ user.payable }}</th>
<th>{{ user.basic_fee }}</th>
<th>{{ user.extra_fee }}</th>
<th>{{ user.basic_call }}</th>
<th>{{ user.basic_traffic }}</th>
<th>{{ user.total_call }}</th>
<th>{{ user.total_traffic }}</th>
<th>{{ user.VPN_service }}</th>
<th>{{ user.extra_call }}</th>
<th>{{ user.extra_traffic }}</th>
<td><a style=" margin:5px auto" class="btn btn-danger btn-sm" href="/delete?phone={{ user.phone }}">删除</a>
<a class="btn btn-warning btn-sm" href="/change?phone={{ user.phone }}">修改</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
首次出现的主要函数或控制字段说明:
函数名 | 功能 |
<tbody> | 绘制表格 |
<tr> | 表格内容开始 |
<th> | 表格内容 |
href="/change?phone={{ user.phone }}" | 高级操作:用?借用网址路由传参,参数限制为字符串或整型 |
网页效果如图:
我不清楚你们直接这样能不能运行,因为增删改查还没写。。。可以先不急着运行。
2.1增
(其实我在运行admin之前先用增传了一些数据进去,方法就是先按下面那个doc格式写好,如何 collection.insert_one(doc)进去),写好增之后你也可以啦,写进去的都能在studio3t里看到,也可直接在studiost里改。
@app.route('/add', methods=['GET', 'POST'])
def add():
# 复制框架源码
if request.method == 'POST':
phone = request.form.get('phone')
name = request.form.get('name')
password = request.form.get('password')
IDnum = request.form.get('IDnum')
ADMIN = request.form.get('ADMIN')
balance = request.form.get('balance')
payable = request.form.get('payable')
basic_fee = request.form.get('basic_fee')
extra_fee = request.form.get('extra_fee')
basic_call = request.form.get('basic_call')
basic_traffic = request.form.get('basic_traffic')
total_call = request.form.get('total_call')
total_traffic = request.form.get('total_traffic')
VPN_service = request.form.get('VPN_service')
extra_call = request.form.get('extra_call')
extra_traffic = request.form.get('extra_traffic')
print('获取的用户信息:', phone, name, password,
IDnum, ADMIN, balance, payable, basic_fee, extra_fee,
basic_call, basic_traffic, total_call,
total_traffic, VPN_service, extra_call, extra_traffic)
doc = {'phone': phone, 'name': name, 'password': password,
'IDnum': IDnum, 'ADMIN': ADMIN, 'balance': balance,
'payable': payable, 'basic_fee': basic_fee,
'extra_fee': extra_fee, 'basic_call': basic_call,
'basic_traffic': basic_traffic,
'total_call': total_call, 'total_traffic': total_traffic,
'VPN_service': VPN_service, 'extra_call': extra_call,
'extra_traffic': extra_traffic}
collection.insert_one(doc)
return redirect('./admin')
return render_template('add.html')
首次出现的主要函数或控制字段说明:
函数名 | 功能 |
request.form.get | 获取从前端传回的数据的一个字段 |
collection.insert_one | monogodb数据库操作,添加一条数据 |
网页效果如图:
2.2删
后端代码:
@app.route('/delete')
def delete_user():
# 在后台需要拿到用户的名字
print(request.method)
phonenum = request.args.get('phone')
# 再传一遍数据库
users = collection.find({}, {'_id': 0})
# 找到用户并删除
for user in users:
if user['phone'] == phonenum:
# 要在数据库里删除user
collection.delete_one({'phone': phonenum})
return redirect('./admin')
首次出现的主要函数或控制字段说明:
函数名 | 功能 |
request.args.get | 获取从前端传回的数据一个结论的一个字段 |
collection.delete_one | monogodb数据库操作,删除一条数据 |
网页效果:点击删除按钮后,管理员页面上立即消失这一条数据。
2.3改
后端
@app.route('/change', methods=["GET", "POST"])
def change_user():
phone = request.args.get('phone')
if request.method == 'POST':
phone = request.form.get('phone')
name = request.form.get('name')
password = request.form.get('password')
IDnum = request.form.get('IDnum')
ADMIN = request.form.get('ADMIN')
balance = request.form.get('balance')
payable = request.form.get('payable')
basic_fee = request.form.get('basic_fee')
extra_fee = request.form.get('extra_fee')
basic_call = request.form.get('basic_call')
basic_traffic = request.form.get('basic_traffic')
total_call = request.form.get('total_call')
total_traffic = request.form.get('total_traffic')
VPN_service = request.form.get('VPN_service')
extra_call = request.form.get('extra_call')
extra_traffic = request.form.get('extra_traffic')
# user = collection.find({}, {'_id': 0})这个好像没用到?
# 加一个update
collection.update_one(
{'phone': phone}, # 筛选出指定数据
{'$set': {
'phone': phone, 'name': name, 'password': password,
'IDnum': IDnum, 'ADMIN': ADMIN, 'balance': balance,
'payable': payable, 'basic_fee': basic_fee,
'extra_fee': extra_fee, 'basic_call': basic_call,
'basic_traffic': basic_traffic,
'total_call': total_call, 'total_traffic': total_traffic,
'VPN_service': VPN_service, 'extra_call': extra_call,
'extra_traffic': extra_traffic
# $set:对当前字典满足筛选器的项进行修改,如果键名不存在则创建键值对
}
})
return redirect('./admin')
users = collection.find({}, {'_id': 0})
for user in users:
if user['phone'] == phone:
# 需要在页面中渲染用户的数据
return render_template('change.html', user=user)
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改</title>
{# 导入框架的css #}
<link rel="stylesheet" href="/static/css/bootstrap.css">
</head>
<body style="background-image: url('...');
background-size: cover;">
<form style="width:400px; margin: 100px auto" method="post" class="form-floating">
<div class="form-floating mb-3">
<input type="text"
class="form-control"
id="exampleInputEmail1"
name="phone"
placeholder="name@example.com"
value="{{ user.phone }}"
>
<label for="exampleInputEmail1" class="form-label">电话号码</label>
</div>
<div class="form-floating mb-3">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="name"
placeholder="name@example.com"
value="{{ user.name }}"
>
<label for="exampleInputPassword1" class="form-label">姓名</label>
</div>
<div class="form-floating mb-3">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="password"
placeholder="name@example.com"
value="{{ user.password }}"
>
<label for="exampleInputPassword1" class="form-label">密码</label>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="IDnum"
placeholder="name@example.com"
value="{{ user.IDnum }}"
>
<label for="exampleInputPassword1" class="form-label">身份证号</label>
</div>
<div class="form-floating mb-3">
{# <input type="text"#}
{# class="form-control"#}
{# id="exampleInputPassword1"#}
{# name="ADMIN"#}
{# placeholder="name@example.com"#}
{# value="{{ user.ADMIN }}"#}
{# >#}
<select name="ADMIN"
class="form-select"
id="floatingSelect"
aria-label="Floating label select example">
<option value="{{ user.ADMIN }}" selected>{{ user.ADMIN }}</option>
<option value="是">是</option>
<option value="否">否</option>
#}
</select>
<label for="exampleInputPassword1" class="form-label">是否管理员</label>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="balance"
placeholder="name@example.com"
value="{{ user.balance }}"
>
<label for="exampleInputPassword1" class="form-label">话费余额</label>
<span class="input-group-text" id="basic-addon2">元</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="payable"
placeholder="name@example.com"
value="{{ user.payable }}"
>
<label for="exampleInputPassword1" class="form-label">本期应付</label>
<span class="input-group-text" id="basic-addon2">元</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="basic_fee"
placeholder="name@example.com"
value="{{ user.basic_fee }}"
>
<label for="exampleInputPassword1" class="form-label">月基本费</label>
<span class="input-group-text" id="basic-addon2">元</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="extra_fee"
placeholder="name@example.com"
value="{{ user.extra_fee }}"
>
<label for="exampleInputPassword1" class="form-label">套餐外费用</label>
<span class="input-group-text" id="basic-addon2">元</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="basic_call"
placeholder="name@example.com"
value="{{ user.basic_call }}"
>
<label for="exampleInputPassword1" class="form-label">套餐含语音通话</label>
<span class="input-group-text" id="basic-addon2">分钟</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="basic_traffic"
placeholder="name@example.com"
value="{{ user.basic_traffic }}"
>
<label for="exampleInputPassword1" class="form-label">套餐含流量</label>
<span class="input-group-text" id="basic-addon2">GB</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="total_call"
placeholder="name@example.com"
value="{{ user.total_call }}"
>
<label for="exampleInputPassword1" class="form-label">语音通话总时长</label>
<span class="input-group-text" id="basic-addon2">分钟</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="total_traffic"
placeholder="name@example.com"
value="{{ user.total_traffic }}"
>
<label for="exampleInputPassword1" class="form-label">流量已使用</label>
<span class="input-group-text" id="basic-addon2">GB</span>
</div>
<div class="form-floating mb-3">
<select name="VPN_service"
class="form-select"
id="floatingSelect"
aria-label="Floating label select example">
<option value="{{ user.VPN_service }}" selected>{{ user.VPN_service }}</option>
<option value="是">是</option>
<option value="否">否</option>
#}
</select>
<label for="exampleInputPassword1" class="form-label">是否开通VPN</label>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="extra_call"
placeholder="name@example.com"
value="{{ user.extra_call }}"
>
<label for="exampleInputPassword1" class="form-label">超出语音</label>
<span class="input-group-text" id="basic-addon2">分钟</span>
</div>
<div class="form-floating mb-3 input-group">
<input type="text"
class="form-control"
id="exampleInputPassword1"
name="extra_traffic"
placeholder="name@example.com"
value="{{ user.extra_traffic }}"
>
<label for="exampleInputPassword1" class="form-label">超出流量</label>
<span class="input-group-text" id="basic-addon2">GB</span>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
</body>
</html>
2.4 查
这里有一个聚合查找,就是姓名手机号身份证号三个选一个搜索就可以出结果。可以自己看一看,其实不难。
@app.route('/search', methods=['GET', 'POST'])
def search():
user = {}
if request.method == 'POST':
# request可以拿到前端浏览器传回的数据
mix = request.form.get('mix')
print(mix)
# name = request.form.get('name')
# IDnum = request.form.get('IDnum')
c1 = collection.count_documents({'phone': mix})
c2 = collection.count_documents({'name': mix})
c3 = collection.count_documents({'IDnum': mix})
count = c1 + c2 + c3
# 先查询返回的值是否存在
# print(phone, password, count)
if count == 0:
# 想return到一个提示错误的网页
return redirect('./search_name_error')
else:
# 跳转到一个查找结果页面search_result,类似admin
# 要传出一个键值对,到底之前给了哪个
condition = {}
if c1 == 1:
condition = {'phone': mix}
elif c2 == 1:
condition = {'name': mix}
else:
condition = {'IDnum': mix}
print(condition)
user = collection.find_one(condition)
# return render_template('search.html', user=user)
return render_template('search.html', user=user)
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>查找</title>
<link rel="stylesheet" href="/static/css/bootstrap.css">
</head>
<body style="background-image: url('...');
background-size: cover;">
<form style="width:400px; margin: 100px auto" method="post">
<div class="container" style="width: auto;margin: auto auto">
<div class="row">
<div class="col-4">
<a class="btn btn-primary" href="/admin">返回</a>
</div>
</div>
</div>
{# <div id="emailHelp" class="form-text">#}
{# 你可以根据手机号、姓名、身份证号中的任意一项进行查询#}
{# </div>#}
<div class="form-floating mb-3"
style="width: auto;margin: 20px auto">
<input type="text"
class="form-control"
id="exampleInputEmail1"
aria-describedby="emailHelp"
placeholder="name@example.com"
name="mix"
>
<label for="exampleInputEmail1" class="form-label">
你可以根据手机号、姓名、身份证号中的任一项查询
</label>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
<div class="container" style="width: auto;margin: 0px auto">
<div class="row">
<div class="col-4">
<a class="btn btn-primary" href="/add">新增用户信息</a>
<a class="btn btn-primary" href="/search">查找</a>
</div>
</div>
</div>
<table class="table table-striped"
style="width: auto;margin: 20px auto">
<thead>
<tr>
<th scope="col">电话号码</th>
<th scope="col">姓名</th>
<th scope="col">密码</th>
<th scope="col">身份证号</th>
<th scope="col">是否管理员</th>
<th scope="col">¥话费余额</th>
<th scope="col">¥本期应付</th>
<th scope="col">¥月基本费</th>
<th scope="col">¥套餐外费用</th>
<th scope="col">套餐含语音通话/min</th>
<th scope="col">套餐含流量/GB</th>
<th scope="col">语音通话总时长/min</th>
<th scope="col">流量已使用/GB</th>
<th scope="col">是否开通VPN</th>
<th scope="col">超出语音/min</th>
<th scope="col">超出流量/GB</th>
</tr>
</thead>
<tbody>
{#需要将python的对象数据显示到浏览器上,模板语法
比较出名的是jinjia2
#}
{# 从数组中取出数据,slice切片,for循环 #}
{# 用法{{ users }} #}
{# {% for user in users %}#}
<tr>
<th>{{ user.phone }}</th>
<th>{{ user.name }}</th>
<th>{{ user.password }}</th>
<th>{{ user.IDnum }}</th>
<th>{{ user.ADMIN }}</th>
<th>{{ user.balance }}</th>
<th>{{ user.payable }}</th>
<th>{{ user.basic_fee }}</th>
<th>{{ user.extra_fee }}</th>
<th>{{ user.basic_call }}</th>
<th>{{ user.basic_traffic }}</th>
<th>{{ user.total_call }}</th>
<th>{{ user.total_traffic }}</th>
<th>{{ user.VPN_service }}</th>
<th>{{ user.extra_call }}</th>
<th>{{ user.extra_traffic }}</th>
<td><a class="btn btn-primary" href="/delete?phone={{ user.phone }}">删除</a>
<a class="btn btn-primary" href="/change?phone={{ user.phone }}">修改</a>
</td>
</tr>
{# {% endfor %}#}
</tbody>
</table>
</body>
</html>
这样就结束了。