【Flask】03-视图和蓝图

工欲善其事,必先利其器。

之前学习了解了基于函数的视图,采用装饰器路由的形式装饰视图函数,本次主要介绍采用类视图的形式,那么当我们采用类视图此时路由如何定义?

接下来让我们一起看看吧!

1. 函数视图

app = Flask(__name__)

def my_list():
    return "列表页"

app.add_url_rule('/list/', endpoint='list', view_func=my_list)

代码发现,我们没有采用传统装饰器的方式定义路由,而是调用了add_url_rule,其中endpoint就是端点,如果没有填写endpoint,那么默认会使用view_func的名字,它主要还是用做url_for反向获取url使用。

app.route(rule,**options)装饰器底层,其实也是使用add_url_rule来实现url与视图函数映射的。

2. 类视图

2.1 标准类视图

from flask import Flask, url_for, views,

class ListView(views.View):
    def dispatch_request(self, *args, **kwargs):
        return "list view"

上面的代码就是一个简单的标准类视图,我们必须重写了dispatch_request方法,以后的请求都会执行这个方法,相当于之前的是视图函数,同时也必须返回Reponse或这子类的对象

为类视图添加路由:

app.add_url_rule('/list/', endpoint='ListView', view_func=ListView.as_view('list'))
  1. ListView.as_view('list')里面必须传个参数name,给view_func起个别名,实际上就是dispatch_request函数
  2. endpoint可以不指定,则默认使用view_func的别名(name参数的值),主要用于url_for反转获取url使用

2. 2 请求类视图

class LoginView(views.MethodView):
    def get(self, error=None):
        return render_template('advanced/login.html', error=error)

    def post(self):
        username = request.form.get("username")
        password = request.form.get("password")
        if username == "ydy" and password == "123":
            return "success"
        else:
            # return render_template('advanced/login.html', error="用户名或密码错误")
            return self.get(error="用户名或密码错误")

    def delete(self):
        pass

    def put(self):
        pass

上述代码模拟了一个登录类视图,和标准类视图相比,所继承的类不同,主要是根据请求方法的不同执行不同的函数。

3. 视图装饰器

接下来,我们看一个模拟登陆认证的装饰器,观察一下他在函数视图和类视图的应用。

from functools import wraps

# 登陆认证装饰器
def login_required(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        username = request.args.get("username")
        if username and username == "ydy":
            return func(*args, **kwargs)
        else:
            return "请登陆"

    return wrapper

@app.route("/user-settings/")
@login_required
def user_settings():
    return "用户设置页"

class ProfileView(views.View):
    decorators = (login_required,)

    def dispatch_request(self):
        return "profile"

通过观察可以发现,传统的视图函数的方式是通过装饰器进行装饰,达到登陆认证的效果,而且自定义的和装饰器需要放在路由装饰器的下面。而想要在类视图中使用请求登录验证的效果,需要重新定义父类的decorators属性,有点像Django中的权限认证的定义。

4. 蓝图

当我们在进行大型项目的开发时,可能需要编写大量的接口代码,同时会定义大量的路由,会导致所有的视图集中在一个文件中,非常的不便于我们的代码的管理和后期的功能代码的添加,那我们可不可以做到类似与Django中app一样,将Flask项目模块化,那么我们就需要使用蓝图。

蓝图作用的就是将项目模块化,相同模块的视图函数存放于统一的蓝图,然后将蓝图注册到app即可。

4.1 蓝图使用

下面就是蓝图的基本语法:

  1. 导入蓝图
from flask import Blueprint
user_bp = Blueprint('user', __name__,url_prefix='/user')

@user_bp.route("/user-info/")
def user_info():
    return render_template('user/user_info.html')

@user_bp.route("/user-settings/")
def user_settings():
    # 注意:在蓝图中,即使是同一个文件进行url反转也要加上蓝图文件名称
    # 不能写成url_for("user_info")
    print(url_for("user.user_info"))
    return "user_settings"
  • user_bp=Blueprint('user', __name__,url_prefix='/user'):定义蓝图,第一个参数指明蓝图名称,第二个参数一般为__name__表示当前模块,url_prefix 会添加到所有与该蓝图关联的 URL 前面。

  • @user_bp.route("/user-info/"):使用蓝图定义路由,其实就是相当于单独的app,所以是@user_bp而不是@app

  • url_for("user.user_info"):通过url_for翻转获取url地址,但是在蓝图中使用,需要使用蓝图名.xxx,不能单独写函数名或endpoint的值

  • 蓝图url前缀

添加前缀就表示这个蓝图所有的视图函数拥有统一的前缀,开发中对于接口url的定义也是按照模块划分,类似于Django/settings下面定义的urls,给每个应用统一一个前缀,前缀定义使用url_prefix参数指定

user_bp = Blueprint('user', __name__, url_prefix="/user")

@user_bp.route("/user-settings/")
def user_settings():
    pass

url_prefix结尾不要加“/”,因为在视图已经加了,防止重复(http://xxxxx/user//user-info/),要不就是蓝图加,视图不加,总之就是防止重复

  1. 注册蓝图
# 导入蓝图
from blueprints.user import user_bp
app = Flask(__name__)
# 注册蓝图
app.register_blueprint(user_bp)

4.2 蓝图模板

user_bp = Blueprint('user',__name__,url_prefix='/user',template_folder='user')

通过template_folder定义模板的路径,但是项目查找模板路径还是先从项目中的templates中查找,如果没有查找到再去蓝图指定目录查找

4.3 蓝图静态文件

user_bp = Blueprint('user',__name__,url_prefix='/user',static_folder='user')
url_for('user.static')

通常我们使用url_for('static')获取静态文件路径,那么就只会在app指定的静态文件夹目录下查找静态文件,如果想要获取蓝图中指定的静态文件目录,需要加上蓝图的名称。

原文地址:https://www.cnblogs.com/ydongy/p/13157756.html