Chapter(Python)(Flask)(视图高级)

Chapter(Python)(Flask)(视图高级),第1张

视图高级
  • 基础知识
    • add_url_rule 与 app.route
    • 类视图
    • 类视图的好处
    • 类视图的调度方法
    • 视图装饰器
  • 蓝图介绍
    • 蓝图目录结构
    • 蓝图模板使用

基础知识 add_url_rule 与 app.route

add_url_rule(rule,view_func=None,endpoint=None):这个方法用来添加url与视图函数的映射

如果没有填写 endpoint ,那么默认会使用 view_func 的名字作为 endpoint 。以后在使用 url_for 的时候,就要看在映射的时候有没有传递 endpoint 参数,如果传递了,那么就应该使用 endpoint 指定的字符串,如果没有传递,那么就应该使用 view_func 的名字

app.route这个装饰器底层,其实也是使用 add_url_rule 来实现url与视图函数映射的

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/', endpoint='func_01')
def func_01():  # put application's code here
    return render_template('index.html')


def func_02_show():
    return '这个是介绍信息'


# endpoint:如果想用 url_for 通过函数名获取路径,没有 endpoint 参数就用函数名,有 endpoint 参数就用这个参数
app.add_url_rule('/show', view_func=func_02_show, endpoint='show')

if __name__ == '__main__':
    app.run()
类视图

之前我们接触的视图都是函数,所以一般简称函数视图。其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图还需要通过 app.add_url_rule(url_rule,view_func) 来进行注册

标准类视图使用步骤

  1. 必须继承自 flask.views.View
  2. 必须实现 dispatch_request 方法,以后请求过来后,都会执行这个方法
  3. 必须通过 app.add_url_rule(rule,endpoint,view_func) 来做url与视图的映射。 view_func 这个参数,需要使用类视图下的 as_view 类方法类转换:ListView.as_view(‘list’)
  4. 如果指定了 endpoint ,那么在使用 url_for 反转的时候就必须使用 endpoint 指定的那个值。如果没有指定 endpoint ,那么就可以使用 as_view(视图名字) 中指定的视图名字来作为反转
from flask import Flask, render_template, url_for
from flask.views import View

app = Flask(__name__)


@app.route('/')
def func_01():
    return render_template('index.html')


class ListView(View):
    # 必须实现这个方法
    def dispatch_request(self):
        return '返回一个List的内容'

app.add_url_rule('/list', view_func=ListView.as_view('ListView'))

if __name__ == '__main__':
    app.run()
类视图的好处

可以继承,把一些共性的东西抽取出来放到父视图中,子视图直接拿来用就可以了

实际上函数视图还是用的最多的

from flask import Flask, render_template, jsonify
from flask.views import View

app = Flask(__name__)


@app.route('/')
def func_01():
    return render_template('index.html')


# 需求:返回的结果都是 JSON
class BaseView(View):

    def get_data(self):
        # 抛出没有实现的错误
        raise NotImplementedError

    def dispatch_request(self):
        return jsonify(self.get_data())


class JsonView_01(BaseView):

    def get_data(self):
        return {'name': '蒋浩', 'age': 20}


class JsonView_02(BaseView):

    def get_data(self):
        return {'name': 'lisi', 'age': 23}


app.add_url_rule('/json01', view_func=JsonView_01.as_view('JsonView_01'))
app.add_url_rule('/json02', view_func=JsonView_02.as_view('JsonView_02'))

if __name__ == '__main__':
    app.run()

类视图的调度方法

基于方法的类视图,是根据请求的 method 来执行不同的方法的。如果用户是发送的 get 请求,那么将会执行这个类的 get 方法。如果用户发送的是 post 请求,那么将会执行这个类的 post 方法。其他的 method 类似,比如 delete 、 put

from flask import Flask, render_template, request
from flask.views import MethodView

app = Flask(__name__)


@app.route('/')
def func_01():
    return render_template('index.html')


# 根据请求方式执行对应的方式
class LoginView(MethodView):

    def get(self):
        pass

    def post(self):
        pass

app.add_url_rule('/login/', view_func=LoginView.as_view('LoginView'))

if __name__ == '__main__':
    app.run()

视图装饰器

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能

在视图函数中使用自定义装饰器,那么自己定义的装饰器必须放在 app.route 下面。否则这个装饰器就起不到任何作用

需求:查看设置个人信息时,只有检测到用户已经登录了才能查看,若没有登录,则无法查看并给出提示信息

from flask import Flask, render_template, request
from functools import wraps
import logging

app = Flask(__name__)


def before_01_login(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        username = request.args.get('username')
        password = request.args.get('password')
        if (username == 'zhangsan' and password == '123'):
            logging.error(f'{username}登录成功')
            return func(*args, **kwargs)
        else:
            logging.error(f'{username}登录失败')
            return '用户名或密码错误'
    return wrapper


@app.route('/')
@before_01_login
def func_01():
    return render_template('index.html')


if __name__ == '__main__':
    app.run()
from flask import Flask, render_template, request
from flask.views import MethodView
from functools import wraps
import logging

app = Flask(__name__)


def before_01_login(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        username = request.args.get('username')
        password = request.args.get('password')
        if (username == 'zhangsan' and password == '123'):
            logging.error(f'{username}登录成功')
            return func(*args, **kwargs)
        else:
            logging.error(f'{username}登录失败')
            return '用户名或密码错误'
    return wrapper

class LoginView(MethodView):

    decorators = [before_01_login]
    def get(self):
        return 'Hello'

app.add_url_rule('/login/', view_func=LoginView.as_view('LoginView'))

if __name__ == '__main__':
    app.run()
蓝图介绍

在 Flask 中,使用蓝图 Blueprint 来分模块组织管理

蓝图实际可以理解为是存储一组视图方法的容器对象,其具有如下特点

  1. 一个应用可以具有多个Blueprint
  2. 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/user” 、 “/goods”
  3. Blueprint可以单独具有自己的模板、静态文件或者其它的通用 *** 作方法,它并不是必须要实现应用的视图和函数的
  4. 在一个应用初始化时,就应该要注册需要使用的Blueprint

注意:Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中

from flask import Flask, render_template, Blueprint

app = Flask(__name__)


@app.route('/')
def func_01():
    return render_template('index.html')

# 创建蓝图
user_bp = Blueprint('user', __name__)

# 蓝图管理子功能
@user_bp.route('/login/')
def func_02_login():
    return '登录模块'

@user_bp.route('/register/')
def func_02_register():
    return '注册模块'

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


if __name__ == '__main__':
    app.run()
蓝图目录结构

为了让项目代码更加清晰,可以通过将代码分在不同的文件里进行管理

在根目录下新建一个 Pyhton文件夹,作为用户模块

# user 文件夹里 __init__.py 内容

from flask import Blueprint
# 创建蓝图
user_bp = Blueprint('user', __name__)

from user import login
# user 文件夹里功能模块文件

from user import user_bp

# 蓝图管理子功能
@user_bp.route('/login/')
def func_02_login():
    return '登录模块'

@user_bp.route('/register/')
def func_02_register():
    return '注册模块'
# 主文件 app.py 里的内容

from flask import Flask, render_template, Blueprint

app = Flask(__name__)


@app.route('/')
def func_01():
    return render_template('index.html')



# 注册蓝图
from user import user_bp
app.register_blueprint(user_bp, url_prefix='/user')


if __name__ == '__main__':
    app.run()
蓝图模板使用

蓝图目录里也可以使用模板,如果蓝图目录文件夹里没有 templates 目录,则默认找最外面的 templates,如果自己有自己的 templates 模板,则在自己的里面找

自己想有自己的模板 HTML 要自己去标注,并且自己模板里的名称和外面模板的名称不能一样,否则就会使用最外面的模板,这是因为他会先去外面的 templates 找,找不到再在里面的 templates 里找

当然里面的你也可以不命名为 templates,这样就不会出现这个问题了

from flask import Blueprint

# 创建蓝图  标注自己的模板文件夹
user_bp = Blueprint('user', __name__, template_folder='templates')

from user import login

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/868523.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存