flask项目流程(二)
-
用户认证模块auth的实现
-
首先需要创建蓝图及其应用注册
-
三步骤
- 创建蓝图
- 运用蓝图
- 注册蓝图
- 创建蓝图
# app\auth\__init__.py
from .models import db
from flask import Blueprint
auth = Blueprint('auth', __name__)
# 切记需要将视图函数导入,不然无法找到
from . import views
- 运用蓝图
# app\auth\views.py
from app.auth import auth
# 添加路由及相应的视图函数
@auth.route('/')
def index():
return "it's my index"
- 注册蓝图
# 在程序工厂函数中注册蓝图
# app\__init__.py
def create_app(env='develop'):
# …………
# 注册蓝图
from app.auth import auth
# 这里添加的前缀需要加上斜杠/
app.register_blueprint(auth, url_prefix='/auth')
return app
用户模块视图函数的编写
功能列表
- 登录
# 表单的制作
class LoginForm(FlaskForm):
phone = StringField('电话', validators=[DataRequired(message='请输入账号'), Regexp(regex='^\d{11}$', message='电话格式错误')])
password = PasswordField('密码', validators=[DataRequired(message='请输入密码'),Length(min=6, message='密码不能短于6位')])
submit = SubmitField('登录')
# views.py
@auth.route('/login', methods=('GET', 'POST'))
def login():
# 实例化表单对象
form = LoginForm()
if form.validate_on_submit():
# 获取表单提交的数据
phone = form.data['phone']
password = form.data['password']
# filter_by返回的是一个列表类型
user = User.query.filter_by(phone=phone).first()
if user:
# 如果用户存在,对密码进行验证
if user.verify_password(password):
# 登录用户
login_user(user)
flash('登录成功', category='success')
return redirect(url_for('auth.index'))
else:
flash('密码错误', category='error')
return redirect(url_for('auth.login'))
else:
flash('用户不存在,请确认账号或者进行注册', category='error')
return redirect(url_for('auth.login'))
return render_template('auth/login.html', form=form)
# auth/login.html
{% extends 'bootstrap/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}登录界面{% endblock %}
{% block content %}
{{ wtf.quick_form(form) }}
{% endblock %}
-
注册(短信验证后续添加)
- 编写form表单进行上传数据
from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import Regexp, \ DataRequired, Length, EqualTo class RegisterForm(FlaskForm): username = StringField('用户名', validators=[DataRequired(message='请输入用户名'),Length(0, 10, message='用户名不能超过10位')]) phone = StringField('电话', validators=[DataRequired(), Regexp(regex='^\d{11}$', message='电话格式错误')]) password = PasswordField('密码', validators=[DataRequired()]) repassword = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password', message='两次密码不一致')]) submit = SubmitField('注册')
- 编写视图函数
@auth.route('/register', methods=('GET', 'POST')) def register(): # 实例化表单对象 form = RegisterForm() # 验证表单数据是否合法并检验提交方式是否为POST方式 if form.validate_on_submit(): # 实例化用户对象 user = User() # form.data 获取表单中的数据,以字典的方式存储 user.username = form.data['username'] user.password = form.data['password'] user.phone = form.data['phone'] db.session.add(user) # 提交到数据库中 db.session.commit() # 进行通知消息的闪现 flash('用户注册成功', category='success') # 注册成功后进行重定向 return redirect(url_for('auth.login')) return render_template('auth/register.html', form=form)
- note:这里需要添加POST方式允许,否则会出下下列报错
这里的html前端页面使用flask-bootstrap快速生成
# flask-bootstrap
https://flask-bootstrap-zh.readthedocs.io/zh/latest/
# 示例
# 继承基模板
{% extends "bootstrap/base.html" %}
# 填充标题
{% block title %}This is an example page{% endblock %}
# 制作导航栏
{% block navbar %}
<div class="navbar navbar-fixed-top">
<!-- ... -->
</div>
{% endblock %}
# 内容
{% block content %}
<h1>Hello, Bootstrap</h1>
{% endblock %}
# 宏操作
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
# 快速生成表单
{{ wtf.quick_form(form) }}
- 注销
在注销之前首先需要用户登录,这里需要使用flask-login,Flask- login为Flask提供用户会话管理。它处理登录、注销和长时间记住用户会话等常见任务。
文档地址:
https://flask-login.readthedocs.io/en/latest/
- 配置信息的修改
login_manager = LoginManager()
# 绑定login_manager和app
login_manager.init_app(app)
-
login_manager的工作原理
您需要提供一个user_loader回调。此回调用于从存储在会话中的用户ID重新加载用户对象。它应该接受用户的unicode ID,并返回相应的user对象
# 可以让我们通过current_user找到当前用户 @loginmanager.user_loader def load_user(user_id): return User.query.get(user_id)
-
其中数据库模型User类需要实现以下四个方法
- is_authenticated 身份验证
- is_active 该账号是否存活
- is_anonymous 是否为匿名用户
- get_id() 回去用户的id
-
其中提供了继承类是我们可以快速实现上述四个方法,User只需要继承Usermixin类
To make implementing a user class easier, you can inherit from
UserMixin
, which provides default implementations for all of these properties and methods. (It’s not required, though.)
-