Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate

1.蓝图

在学习过 Django 后,我们了解到 Django 中的 app 主要作用就是将 Django 项目划分成一个个单独的 app 模块,然后将所有 app 分配不同的处理功能,通过路由分配将它们连接成一个大的Django 项目,而在 Flask 中的蓝图与 Django 中的 app 有异曲同工之妙。

下面我们大致来了解一下 Flask 的蓝图,首先创建一个主的路由配置文件 app.py,该文件主要的作用就是启动整个的 Flask 框架;

from flask import Flask

# 创建Flask的主app
app = Flask(__name__)
app.debug = True

# app.py中的部分路由
@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    print(app.url_map)
    # 启动主app
    app.run()

   接着我们在 app.py 的同级目录下创建 user/views.py 和 cart/views.py ,内容大致如下;

# user/views.py
from flask import Blueprint

# 这里注意路径的不同
# 静态文件查找
# bp = Blueprint("user",__name__,url_prefix="/user/",static_folder='static')
# 模板文件查找
bp = Blueprint("user",__name__,url_prefix="/user/",static_folder='staticfiles',template_folder='templates')

@bp.route("/")
def index():
    return render_template('user.html')
# cart/views.py
from flask import Blueprint

# 创建一个蓝图,Blueprint必须指定两个参数,cart表示蓝图的名称,__name__表示蓝图所在模块
bp = Blueprint("cart",__name__,url_prefix="/cart/")

# 用该蓝图来设置路由方法
@bp.route("/")
def index():
    return "cart blueprint"

   Flask 是通过蓝图注册方式将蓝图添加到主 app 中,而这两个 py 文件主要是创建蓝图,接着为创建的蓝图添加路由配置;

from flask import Flask
from user import views as UserViews
from cart import views as CartViews

# 创建Flask的主app
app = Flask(__name__)
app.debug = True

# 注册分路由  将蓝图注册到app
app.register_blueprint(UserViews.bp)
app.register_blueprint(CartViews.bp)

# app.py中的部分路由
@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    print(app.url_map)
    # 启动主app
    app.run()

   由于 user/views.py 处返回的是一个 user.html 页面,下面我们对其进行编写;




    
    Title


    user page
    
    
    
    登录

   这样配置好就可以实现路由分层管理,运行主程序进行访问,效果如下;

 Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第1张图片 Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第2张图片

2.类视图 

   完成一个简单的登录验证的小案例来了解类视图,若已登录成功会跳转至商品搜索页面,否则回到登录页面。首先在主目录下创建 goods/views.py,编写一个类视图的简单使用;

from flask.views import MethodView
from flask import render_template,request
from user.views import login_required

class GoodsView(MethodView):
    def get(self):
        return render_template('goods.html')

    def post(self):
        q = request.form.get('q')
        return q

   接着把渲染模板 goods.html 的代码编写上;




    
    Title


    
商品详情

   在主 app 上注册路由;

from goods.views import GoodsView
app.add_url_rule('/goods/',view_func=GoodsView.as_view('goods'))

   并在 user/views.py 中简单的编写登录注销的视图函数及定义装饰器;

import functools
from flask import Blueprint,render_template,session,url_for,redirect

# bp = Blueprint("user",__name__,url_prefix="/user/",static_folder='static')
bp = Blueprint("user",__name__,url_prefix="/user/",static_folder='staticfiles',template_folder='templates')

def login_required(func):
    # 添加后路径名字不会变化,反转时不用修改
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        if not session.get("is_login"):
            return redirect(url_for('user.login'))
        return func(*args,**kwargs)
    return wrapper

@bp.route("/")
@login_required
def index():
    # return "user blueprint"
    return render_template('user.html')

@bp.route("/login/")
def login():
    session['is_login'] = True
    return render_template('login.html')

@bp.route("/logout/")
def logout():
    session.clear()
    return "session clear"

   在 GoodsView() 视图函数中使用登录验证装饰器;

from flask.views import MethodView
from flask import render_template,request
from user.views import login_required

class GoodsView(MethodView):
    @login_required
    def get(self):
        return render_template('goods.html')

    def post(self):
        q = request.form.get('q')
        return q

   其他视图使用直接在视图函数中添加@login_required即可;

@bp.route("/")
@login_required
def index():
    # return "user blueprint"
    return render_template('user.html')

   效果如下(在还没登录前访问会跳转到登录页面):

  Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第3张图片   Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第4张图片

3.Flask_login

   上面是自己编写的登录验证,接下来使用 Flask 框架提供的 Flask_login 来登录验证。

   安装

   在使用前先进行安装:pip install Flask-Login==0.3.2

   配置

   在安装完之后,在 app.py 主 app 中进行配置;

from flask_login import LoginManager

login_manager = LoginManager()
login_manager.init_app(app)

# 设置登录跳转及消息
login_manager.login_view = 'user.login'
login_manager.login_message = u""

   重构用户模型

   登录基于用户,需要定义 User 类,Flask-Login 规定 User 类必须实现三个属性和一个方法:

   (1)is_authenticated 属性,一般而言,这个属性应该只返回 True,除非表示用户的对象因为某些原因不允许被认证;

   (2)is_active 属性应该返回 True,除非是用户是无效的,比如因为他们的账号是被禁止;

   (3)is_anonymous 属性应该返回 True,除非是伪造的用户不允许登录系统;

   (4)get_id 方法应该返回一个用户唯一的标识符,以 unicode 格式。我们使用数据库生成的唯一的 id。需要注意地是在 Python 2 和 3 之间由于 unicode 处理的方式的不同我们提供了相应的方式。

   这里最简单的方法就是从 UserMixin 类继承,该类提供了默认的实现。在 user/models.py 文件中编写代码如下;

from db.ext import db
from flask_login import UserMixin

# 用户模型
class UserModel(UserMixin,db.Model):
    # 定义表名
    __tablename__ = "user"
    # 类型ID、类型名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(64), unique=True)
    # 关联
    password = db.Column(db.String(64), unique=True)

    def __str__(self):
        return self.username

class BookModel(db.Model):
    __tablename__ = "book"
    # 类型ID、类型名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    bookname = db.Column(db.String(64), unique=True)

    def __str__(self):
        return self.bookname

   再在 user/views.py 中引入上述编写的用户模型,并进行注册;

import json
from flask import render_template, session, redirect, url_for, request, flash
from flask.views import MethodView
from flask_login import login_user, logout_user
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField,PasswordField
from wtforms.validators import DataRequired
from .models import UserModel

# 登录功能实现
class LoginForm(FlaskForm):
    username = StringField(u'用户名',validators=[DataRequired()])
    password = PasswordField(u'密码',validators=[DataRequired()])
    submit = SubmitField(u'提交')

# 统一用类视图
class LoginView(MethodView):
    def get(self):
        login_form = LoginForm()
        return render_template('login.html',form=login_form)
    def post(self):
        login_form = LoginForm()
        if login_form.validate_on_submit():

            username = request.form.get('username')
            password = request.form.get('password')

            user = UserModel.query.filter_by(username=username,password=password).first()

            # if username == "admin" and password == "112233":
            if user:
                # 登录成功
                # session['is_login'] = True
                # session['username'] = username
                login_user(user,force=True)
                next = request.args.get('next',None)
                if not next:
                    return redirect(url_for('index'))
                else:
                    return redirect(next)
                return redirect(url_for('index'))
            else:
                flash("登录失败")
                return render_template('login.html',form=login_form)

# 登出功能实现
class LogoutView(MethodView):
    def get(self):
        # session.clear()
        logout_user()
        return redirect(url_for('user.login'))
# 注册路由
app.add_url_rule('/user/login/',view_func=LoginView.as_view('user.login'))
app.add_url_rule('/user/logout/',view_func=LogoutView.as_view('user.logout'))

   在 index/views.py 中设置登录限制;

from flask import render_template
from flask.views import MethodView
from flask_login import login_required, current_user

class IndexView(MethodView):
    @login_required
    def get(self):
        return render_template("index.html",username=current_user.username)

   接着,在模板 index.html 中访问当前变量;




    
    Title


    欢迎您,{% if current_user.is_authenticated %}
                {{ username }}
           {% endif %}
    退出

   user_loader 回调 

   这里我们必须编写一个函数用于从数据库加载用户,在 app.py 中使用;

# 设置 load_user 回调
@login_manager.user_loader
def load_user(userid):
    return UserModel.query.get(userid)

   效果如下:

   当用户的用户名、密码核实正确后会跳转到欢迎登录界面,若失败则会提示登录失败。

        Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第5张图片  Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第6张图片

                                   Flask 框架(五)— 蓝图、类视图、Flask_login、Flask-Migrate_第7张图片

4.Flask-Migrate

   flask-migrate 是基于 Alembic 进行的一个封装,并集成到 Flask 中, 而所有的迁移操作其实都是 Alembic 做的,他能跟踪模型的变化,并将变化映射到数据库中。

   先进行安装:pip install flask-migrate,还需要再 app.py 中绑定 app 和数据库;

from flask_migrate import Migrate
# Migrate管理app里的数据库
migrate = Migrate(app,db)

   生成数据库的操作:

# 初始化一个迁移文件夹
flask db init
# 把当前的模型添加到迁移文件中
flask db migrate
# 把迁移文件中对应的数据库操作,真正的映射到数据库中
flask db upgrade

你可能感兴趣的:(flask,python,django)