当前位置:   article > 正文

Day4 --- Flask 上下文与蓝图_flask 蓝图 上下文处理

flask 蓝图 上下文处理

昨日回顾

  • 使用session如何进行状态保持?
  • 使用cookie如何进行状态保持?
  • flask中可以应用哪个函数主动抛出异常?
  • abort如何配合异常处理函数使用?
  • flask请求钩子分为几类? 每一个的特点是什么?

今日内容

  • Flask上下文
  • 蓝图
  • 初识Flask-RESTful
  • 视图类的装饰器

1. Flask上下文

1.1 概念与上下文对象

上下文:即语境,语意,在代码执行到某一时刻时,根据之前代码所做的操作以及下文即将要执行的逻辑,决定在当前时刻可以使用的变量。

上下文对象分类

  • 请求上下文, request & session
  • 应用上下文, current_app & g对象

1.2 请求上下文之request与session

request,封装了http内容,贯穿整个处理流程,直到返回响应。

session, 用户信息的会话保持。

1.3 应用上下文current_app与g对象

current_app事实上是Flask实例的代理,由于一个项目只能有一个app实例,在其他地方使用app需要导入,不方便使用! current_app就是APP的全局代理。在不方便操作flask的APP对象时,可以操作current_app,就等价于操作APP实例。

current_app用于存储应用程序中的变量:

  • 应用的启动脚本是哪个文件, 启动时指定了哪些参数
  • 加载了哪些配置文件
  • 连接了哪个数据库
  • 有哪些public的工具类
  • 应用跑在哪个机器上, IP是多少,内存多大等等信息

g对象,flask的一个全局临时变量, 可在多个视图函数间共享数据, 每次请求都会重设这个变量。(随着请求的创建而创建,销毁而销毁)

# g对象实例
from flask import Flask, g

app = Flask(__name__)

@app.before_request
def bb():
    print("处理请求之前:")
	# 连接数据库
    g.db_conn = pymysql.connect(
        host="localhost", 
        port=3306, 
        user="lauf", 
        password="lauf123", 
        database="world")

    # 请求继续向后走
    return None

@app.route("/test_g/")
def test_abort():
    # 获取g对象的属性
    db = g.db_conn

    # 查询数据
    cursor = db.cursor()
    cursor.execute("select * from stu;")
    data = cursor.fetchall()

    return json.dumps(data)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

1.4 手动开启上下文

在flask程序未运行时, current_app, g, request这些对象无法使用, 调试时需要手动开启上下文。

app_context为我们提供了应用上下文环境, 允许我们在外部使用应用上下文current_app, g。可以通过with语句开启上下文。

# app_context 函数
>>> from flask import Flask
>>> app = Flask('')
>>> app.redis_cli = 'redis client'
>>> 
>>> from flask import current_app
>>> current_app.redis_cli   # 错误,没有上下文环境
报错
>>> with app.app_context():  # 开启应用上下文
...     print(current_app.redis_cli)
...
redis client

# request_context
# request_context为我们提供了请求上下文环境,允许我们在外部使用请求上下文request、session可以通过with语句进行使用
>>> from flask import Flask
>>> app = Flask('')
>>> request.args  # 错误,没有上下文环境
报错
>>> environ = {'wsgi.version':(1,0), 'wsgi.input': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/', 'SERVER_NAME': 'itcast server', 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80'}  # 模拟解析客户端请求之后的wsgi字典数据
>>> with app.request_context(environ):  # 借助with语句使用request_context创建请求上下文
...     print(request.path)
...   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2. 蓝图

2.1 蓝图的概念

在Flask中,蓝图(blueprint)是一种扩展Flask应用结构的方式,蓝图可以把功能类似的视图函数组合在一起,把应用拆分成不同的组件。 蓝图的作用类似于控制器(controller).

蓝图的使用步骤:

  1. 创建一个蓝图对象
  2. 为蓝图,注册路由, 指定静态文件夹,注册模板过滤器
  3. 注册蓝图对象(在应用对象app上)

2.2 蓝图的实现

# apps.users模块
# 1. 创建蓝图
from flask import Blueprint

# 创建蓝图对象
users_bp = Blueprint('users', __name__)

# 2. 添加蓝图路由
@users_bp.route('/index/')
def indext():
    return 'users bp response'

# 3.注册蓝图, 在app主模块
from flask import Flask
# 从导入蓝图
from apps.users_bp import users_bp

# 创建Flask实例
app = Flask(__name__)
# 注册蓝图
app.register_blueprint(users_bp)

if __name__ == '__main__':
    # 查看路由映射
    print(app.url_map)
    app.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3. 初识Flask-RESTful

3.1 安装配置与第一个restful测试

# 安装flask-restful扩展
pip install flask-restful
  • 1
  • 2

基本使用

  1. 导入Api与Resource,api用于创建接口,Resource用于定义视图类
  2. 创建api对象 api=API(app)
  3. 自定义视图类, 必须继承Resource
  4. 视图类中定义请求方法
  5. 使用api对象添加路由
# 简单接口的实现
from flask import Flask
# 1.导入Api, Resource
from flask_restful import Api, Resource

app = Flask(__name__)
# 2.创建api对象
api = Api(app)


# 3.自定义视图类(继承Resource)
class IndexResource(Resource):
    # 4.在视图类中定义请求方法
    def get(self):
        # 返回响应
        return 'first restful api'


# 5. api对象的add_resource()添加路由
	# IndexResource是视图
    # '/index'是路由
    # endpoint是路由别名
api.add_resource(IndexResource, '/index', endpoint='index')


# 程序入口
if __name__ == '__main__':
    app.run(debug=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.2. Flask-RESTful配合蓝图

1.创建蓝图文件, 编写蓝图代码:
- 创建蓝图对象
- 创建蓝图api接口对象
- 编写蓝图的视图类
- 给蓝图视图添加路由
2.创建主程序, 编写主程序代码:
- 导入蓝图对象
- 创建Flask实例对象
- 创建Flask实例的api对象
- 注册蓝图
- 程序运行

# users.py 用户蓝图 模块
from flask import Blueprint
from flask_restful import Api, Resource

# 创建蓝图对象
users_bp = Blueprint('users', __name__)
# 创建接口api对象
api = Api(users_bp)

# 创建蓝图视图
class IndexResource(Resource):
    def get(self):
        return 'users_bp.api'

# 添加蓝图路由
api.add_resource(IndexResource, '/index/', endpoint='index')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

主程序:

# 主程序编码
from flask import Flask
from flask_restful import Api, Resource
# 导入蓝图
from apps.users import users_bp

app = Flask(__name__)
api = Api(app)
# 注册蓝图
app.register_blueprint(users_bp)

if __name__ == '__main__':
    # 查看路由映射
    print(app.url_map)
    app.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.3 练习

  1. 创建apps.books模块,模块内定义一个book_bp, 并使用restful方式定义api对象和视图类BookList;

  2. BookList内部实现get请求加载表books_tb中的所有的书籍数据。数据库的连接对象在处理请求之前创建,并放到g对象上面。

  3. apiPost测试接口。

4. 视图类的装饰器

4.1 为所有方法添加装饰器

# 装饰器
def decorator1(func):
      def wrapper(*args, **kwargs):
          print('decorator1')
          return func(*args, **kwargs)
      return wrapper


def decorator2(func):
    def wrapper(*args, **kwargs):
        print('decorator2')
        return func(*args, **kwargs)
    return wrapper


# 定义视图类
class DemoResource(Resource):
	# 类属性!!
    method_decorators = [decorator1, decorator2]

    def get(self):
        return {'msg': 'get view'}

    def post(self):
        return {'msg': 'post view'}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

以上为类内所有的方法添加decorator1、 decorator2

4.2 为单个方法指定装饰器

# 指定方法加装饰器
class DemoResource(Resource):
      method_decorators = {
          'get': [decorator1, decorator2],
          'post': [decorator1]
      }

      # 使用了decorator1 decorator2两个装饰器
      def get(self):
          return {'msg': 'get view'}

      # 使用了decorator1 装饰器
      def post(self):
          return {'msg': 'post view'}

      # 未使用装饰器
      def put(self):
          return {'msg': 'put view'}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/501434
推荐阅读
相关标签
  

闽ICP备14008679号