Flask-Blueprint (蓝图)

Flask-Blueprint (蓝图)

什么是蓝图

在Flask项目中可以用Blueprint(蓝图)实现模块化的应用,使用蓝图可以让应用层次更清晰,开发者更容易去维护和开发项目。蓝图将作用于相同的URL前缀的请求地址,将具有相同前缀的请求都放在一个模块中,这样查找问题,一看路由就很快的可以找到对应的视图,并解决问题了。

程序结构可以变为

application
users模块
vote模块
report模块

这些模块使用Blueprint可以拥有自己的url前缀地址进行区分

# 模块内 views.py文件
from flask import Blueprint
users = Blueprint('users', __name__)

@users.route('/register')
def register():
    return '注册页面'
# application/__init__.py

# 放在db = SQLAlchemy(app)这条语句后面
from application.users.views import users

# 注册蓝图
app.register_blueprint(users, url_prefix='/users')

在application下创建templates目录, 分模块存放页面,继承base.html

Flask-WTF - 表单验证和渲染组件

安装

$ pip install flask-wtf
from flask_wtf import FlaskForm
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField
from wtforms import ValidationError
from wtforms.validators import DataRequired, Length
from application.users.models import Users

class RegisterForm(FlaskForm):
    username = StringField('用户名', validators=[ DataRequired(), Length(max=128) ])
    password = PasswordField('密码', validators=[ DataRequired(), Length(min=6, message='密码不能小于6位.') ])
    fullname = StringField('姓名', validators=[ DataRequired(), Length(max=128) ])
    submit = SubmitField('提交')

    # 验证用户名是否存在
    def validate_username(self, field):
        if Users.query.filter_by(username=field.data).first():
            raise ValidationError('用户名已存在.')

使用Flask-Login认证用户

用户登录程序后,他们的认证状态要被记录下来,这样浏览不同的页面时才能记住这个状 态。Flask-Login 是个非常有用的小型扩展,专门用来管理用户认证系统中的认证状态,且不依赖特定的认证机制。

$ pip install flask-login 

要想使用 Flask-Login 扩展,程序的 Users 模型必须实现几个方法
is_authenticated()
如果用户已经登录,必须返回True,否则返回False
is_active()
如果允许用户登录,必须返回 True,否则返回 False。如果要禁用账户,可以返回 False
is_anonymous()
对普通用户必须返回 False
get_id()
必须返回用户的唯一标识符,使用 Unicode 编码字符串

这 4 个方法可以在模型类中作为方法直接实现,不过还有一种更简单的替代方案。Flask- Login 提供了一个 UserMixin 类,其中包含这些方法的默认实现,且能满足大多数需求。

from flask_login import UserMixin
from application import db
import datetime

# 用户表
class Users(UserMixin, db.Model):
    __tablename__ = 'users'
    # 主键
    id = db.Column(db.Integer, primary_key=True)
    # 用户名 唯一索引
    username = db.Column(db.String(128), unique=True, nullable=False)
    # Hash密码  必填字段
    password = db.Column(db.String(512), nullable=False)
    # 姓名 创建索引,加快查询
    fullname = db.Column(db.String(128), index=True, nullable=False)
    # 状态 (1: 生效 0: 禁用)
    status = db.Column(db.SmallInteger, default=1, nullable=False)
    # 创建时间 默认当前时间
    created_time = db.Column(db.DateTime, nullable=False, default=datetime.datetime.now, index=True)

    def __repr__(self):
        return 'username=%s' % self.username    

Flask-Login 在application/init.py中初始化

from flask_login import LoginManager

# 初始化LoginManager
login_manager = LoginManager()
# 设为 'strong' 时,Flask-Login 会记录客户端 IP 地址和浏览器的用户代理信息,如果发现异动就退出用户
login_manager.session_protection = 'strong'
# login_view 属性设置登录页面
login_manager.login_view = 'users.login'

login_manager.init_app(app)

LoginManager 对象的 session_protection 属性可以设为 None、’basic’ 或 ‘strong’,以提 供不同的安全等级防止用户会话遭篡改。设为 ‘strong’ 时,Flask-Login 会记录客户端 IP 地址和浏览器的用户代理信息,如果发现异动就退出用户。login_view 属性设置登录页面 的端点。

Flask-Login 要求程序实现一个回调函数,使用指定的标识符加载用户。

from application import login_manager 
@login_manager.user_loader
def load_user(user_id):
 	return Users.query.get(int(user_id))

保护路由

为了保护路由只让认证用户访问,Flask-Login 提供了一个
login_required 装饰器。用法演示如下:

from flask_login import login_required 
@app.route(‘/secret’)
@login_required
def secret():
 return '只有登录用户可以看'

如果未认证的用户访问这个路由,Flask-Login 会拦截请求,把用户发往登录页面

# 验证成功,登录用户
login_user(user, remember=form.remember_me)

login_user() 函数的参数是要登录的用户,以及可选的“记住我”布 尔值,“记住我”也在表单中填写。如果值为 False,那么关闭浏览器后用户会话就过期 了,所以下次用户访问时要重新登录。如果值为 True,那么会在用户浏览器中写入一个长 期有效的 cookie,使用这个 cookie 可以复现用户会话。

 

判断条件中的变量 current_user 由 Flask-Login 定义,且在视图函数和模板中自动可用。 这个变量的值是当前登录的用户,如果用户尚未登录,则是一个匿名用户代理对象。如果 是匿名用户,is_authenticated() 方法返回 False。所以这个方法可用来判断当前用户是否 已经登录。

总体步骤

  1. 搭建一个Flask package的框架(参见第二天的框架)

    school(项目目录)
    	application (package)
            __init__.py
            views.py
            models.py
    	manager.py
    

    演变为Blueprint结构

    school(项目目录)
    	application (项目package)
    		__init__.py
    		users(模块package)
    			__init__.py
    			models.py
    			views.py
    			forms.py
    		home(模块package)
    			__init__.py
    			...
    		templates(项目模板)
    			users(模板目录)
    			home(模板目录)
    			...
    		static
    			js
    			css
    			images
    	manager.py	
    
  2. 在各模块的views.py里面生成Blueprint对象,在application/__init__.py里面注册各模块的Blueprint对象和url前缀

  3. 在views.py里面编写使徒的方法

    1. 注册功能 def register

    2. 在templates里面编写对应的模板页register.html(Jinja2)

    3. 创建母版页layout.html,为其他页面实现公用

    4. 新建forms.py(Flask-WTF), 根据表单增加相应的字段,字段加入校验的规则,验证用户是否存在可以加在forms.py里面的(validate_user(field名))

    5. 在views.py里面创建form对象,并将form对象传给页面

    6. 页面是渲染表单,显示隐藏标签(form.hidden_tag)->csrf_token

      form.username.lable :生成用户 form.username:生成输入框

      form.submit

    7. 在整个过程中使用url_for(‘xxx.xxx’)生成url ,xxx.xxx是模块views.py中的方法名

    8. 在views.py方法上面如果是get和post方法,需要在路由中加入methods=[‘GET’, ‘POST’]

    9. form.validated_on_submit()进行表单验证,如果验证失败,在页面显示错误信息,使用法flash()推送通用整体消息到页面,各字段的错误(form.username.errors),使用模板macro定义了的通用错误信息的方法,macros.html,在layout里面import macros.html,页面可以通用

    10. 如果表单验证通过,生成Users对象,password做了generate_password_hash,db.session.add(user),db.session.commit(),return redirect(‘url_for()’)

    11. 登录模块,生成表单一样的步骤;user = Users.query.filter_by(username=username).first()

      ,验证密码是否正确使用check_password_hash(password_hash, password)

    12. 使用Flask_Login模块里面的login_user方法自动登录用户,编写了load_user回调函数(从数据库中加载当前登录的对象),可以通过current_user拿到当前登录用户,用current_user.is_authenticated()判断用户是否登录

你可能感兴趣的:(Flask文档)