代码实现详解
本章中我将会介绍templates和view下的文件和函数。
templates目录下都是html模板文件,内容如下
├── index.html
├── layout.html
└── login
├── change_password.html
├── login.html
├── role_add.html
├── role_edit.html
├── role_management.html
├── user_add.html
└── user_management.html
views目录下只有两个文件,其中__init__.py是空文件,login.py是主要文件
├── init.py
├── login.py
因为这些文件都是互相调用和指向,所以我会从功能的实现来解读
用户登录
我们通过判断session中是否存在 username来检查用户是否登录,所以在login.py中有如下的修饰函数
def login_required(view):
"""View decorator that redirects anonymous users to the login page."""
@functools.wraps(view)
def wrapped_view(**kwargs):
if session.get("username") == None:
return redirect(url_for('login.login'))
return view(**kwargs)
return wrapped_view
这个函数如果检测到session中不存在username,则会转向login.py文件中的login函数
@bp.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'POST' :
username = request.form['username']
password = hashlib.sha224(request.form['password'].encode()).hexdigest()
user_info = USERS.query.filter_by(username=username,password=password).all()
if len(user_info)==0:
flash ("Wrong Username or Password")
return render_template('login/login.html')
else:
userrole = user_info[0].userrole
session['username']=username
session['userrole']=userrole
return redirect(url_for('login.success'))
return render_template('login/login.html')
因为这个转页不是post方法,所以login函数则会直接弹出templates目录下login.html文件让用户输入用户名和密码。
<form class="form-signin" method="POST" action="{
{url_for('login.login') }}">
{% if get_flashed_messages() %}
<h1 class="h4 mb-3 font-weight-normal">{
{ get_flashed_messages()[0] }}</h1>
{% endif %}
<h1 class="h4 mb-3 font-weight-normal">Please sign in</h1>
<label for="username" class="sr-only">Username</label>
<input type="text" name="username" id="username" class="form-control" placeholder="Username" required autofocus>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
这个文件中的将会把username和password传给上面login函数,因为这一次是post的方法,所以login函数会去验证user表中是否有相同的用户名和密码。
- 如果用户名密码正确,就把username和userrole加到session中,并转入login.success函数
- 如果错误,则会转回登录界面,并提示。
其中密码我们使用了sha224加密,这也是为什么我们设置密码为Password123!但是插入数据库的时候是一串很长字符的原因。
而login.success函数,则主要做如下事情:
- 从menus获取所有的菜单信息,包括menuid,menuname和parentmenu
- 从rolemapping表中获得用户角色对应的所有menuid
- 将这些信息存入session,然后渲染index.html页面
@bp.route('/success')
@login_required
def success():
roleid=session['userrole']
all_menus = MENUS.query.order_by(MENUS.menuorder).all()
menus=[]
for menu in all_menus:
menu_detail=[menu.menuid,menu.menuname,menu.parentmenu]
menus.append(menu_detail)
session['menus']=menus
mappings = ROLEMAPPINGS.query.filter_by(roleid=roleid).all()
mapping_menus=[]
for mapping in mappings:
mapping_menus.append(mapping.menuid)
session['mapping_menus']=mapping_menus
return render_template('index.html')
index.html就是登陆成功以后的主页面,包括下拉菜单和主要内容,因为这个教程主要是讲怎么实现基于角色的菜单控制,所以主要内容基本为空。
{% extends 'layout.html' %}
{% block content %}
<div class="col-xl-9">
<div class="mb-3">
<h3 class="display-8 card p-3">Welcome {
{session['username']}}</h3>
</div>
</div>
{%endblock%}
而第一行的layout.html,才是我们下拉菜单需要的主要文件。下拉菜单的实现是使用了Bootstrap的navbar。
其实现模式可以参考https://getbootstrap.com/docs/4.4/components/dropdowns/
一个最简单的下拉菜单如下
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false