FLASK---高级处理

一:钩子函数:

from flask import Flask, make_response, Response, request

app = Flask(__name__)

@app.before_first_request
def inital():
    """
    第一次请求之前调用,并且只会调用一次。
    作用:项目的初始化操作
    :return: 不要返回值,如果存在返回值会之间返回给前端,就进入不了视图函数
    """
    print("请求之前,只调用一次")
@app.before_request
def process_request():
    """
    每次请求之前调用
    作用:封ip, 统一用户权限认证,用户信息的提取
    :return:不需要返回值
    """
    print("请求之前调用,每次请求都会调用")

@app.after_request
def process_response(response):
    """
    # 每一次视图执行之后调用。
    作用:拦截响应对象进行统一设置。
    :param response:视图函数返回的响应。
    :return: 一定要返回响应,不返回前端获取不到响应。
    """
    print("我在请求之后被调用了,每次请求之后都会被调用")
    return response

@app.teardown_request
def process_error(error):
    """
    每次请求结束的时候调用
    作用:判断处理异常,收尾工作
    :param error:异常处理对象
    :return:
    """
    print(error)
    print("我会接收异常信息")
    
@app.route('/login')
def login():
    print("我是视图函数,我被调用了")
    return ""

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

运行结果:
在这里插入图片描述

二:蓝图:

  • 1: 在模块的初始化文件,创建蓝图对象。
  • 2:在视图文件中,利用蓝图对象绑定路由信息。
  • 3:将蓝图对象注册到app中。
  • 4:在模块的初始化文件中导入视图文件中的视图。

1:案例:

  • 初始化文件做两件事:1:创建蓝图对象。 2:导入视图。
  • 视图文件中一件事:利用蓝图对象绑定路由。
  • 主初始化文件一件事:将蓝图对象注册到app中。

1: 在home的__init__文件中的代码:

from flask import Blueprint
"""
1: 蓝图中可以创建属于自己的模板和静态文件
2: 创建蓝图对象的参数: 蓝图名称, 导包路径
"""
# 1: 创建蓝图对象
home_bp = Blueprint("home", import_name=__name__)

from home.views import *

2: 在home的views文件中的代码:

from home import home_bp
"""
蓝图对象没有注册视图路由的能力
"""
@home_bp.route('/home')
def home_page():
    return "home page"

3:main.py中的代码:

from flask import Flask, make_response, Response, request
from home import home_bp

app = Flask(__name__)

app.register_blueprint(home_bp)

@app.route('/login')
def login():
    print("这是登录函数")
    return "登录函数"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

2: 循环导包问题:

  • __init__初始化文件中导入视图函数,必须在创建完蓝图对象之后导包。

解析循环导包:
如下图,在初始化文件中,from . import views会导入views中的视图,但是views中又需要导入home_bp这个蓝图对象,所以又回到__init__初始化文件中导入蓝图对象。这样就造成循环导包。

解决方案:延迟导包。导入views的过程,放在创建蓝图对象之后。
在这里插入图片描述

3:蓝图的3个使用细节:

  • 1:创建蓝图时, 可以通过 url_prefix参数 给蓝图定义的路由添加 统一的URL资源段前缀。
  • 2:蓝图定义的路由, 其函数标记为 蓝图名.函数名。
  • 3:蓝图也可以 设置请求钩子,但是只有访问该蓝图定义的路由时才会触发,实现局部监听。

案例一:修改__init__文件后,我们发现需要访问/home/home才能访问到视图,因为,蓝图设置一次,视图又设置一次。

from flask import Blueprint
"""
1: 蓝图中可以创建属于自己的模板和静态文件
2: 创建蓝图对象的参数: 蓝图名称, 导包路径
"""
# 1: 创建蓝图对象
home_bp = Blueprint("home", import_name=__name__, url_prefix="/home")

from home.views import *

案例二:蓝图中使用url_for根据函数名获取url路由:
注意:home.homepage:home是蓝图名,homepage是函数名。

from flask import url_for

from home import home_bp
"""
蓝图对象没有注册视图路由的能力
"""
@home_bp.route('/home')
def home_page():
    url = url_for("home.home_page")
    print(url)
    return "home page"

案例三:蓝图中使用;钩子函数:

from flask import Blueprint
"""
蓝图中创建的钩子函数,只对当前蓝图起作用,对其他蓝图不起作用
"""
# 1: 创建蓝图对象
home_bp = Blueprint("home", import_name=__name__, url_prefix="/home")

@home_bp.before_request
def home_pre_prepare():
    print("home_prepare")

from home.views import *

三:上下文:

  • 1:上下文就是一个数据容器。
  • 2:上下文分为请求上下文和应用上下文。
  • 3:请求上下文分为request和session。
  • 4:应用上下文分为current_app 和 g。
  • 5:导包都是from flask import request, session, current_app, g。
  • 6:本质都不是全局变量,底层通过线程进行了隔离。
  • 7:生命周期:请求开始时创建,返回响应时销毁。
  • 8:作用范围:默认只能视图函数内部使用,函数外部使用会报错。

1:请求上下文:

  • 注意session的使用需要设置加密密钥。
from flask import Flask,request, session

app = Flask(__name__)
app.secret_key = 'renshanwen@@@'

@app.route('/login')
def login():
    # 请求上下文的使用---request:
    print(request.headers)
    print(request.url)
    print(request.remote_addr)
    print(request.remote_user)


    # 请求上下文的使用---session
    session['user'] = 'renshanwen'
    print(session.get('user'))
    print()
    return ""
    
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

2:应用上下文:

<一>: current_app的使用:

作用:当模块中够不到app时,想调用app中的配置,使用current_app获取。

from flask import Flask,current_app

app = Flask(__name__)

@app.route('/login')
def login():
    print(current_app.url_map)
    return "hello"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
<二>: g变量的使用:
  • 1:能在钩子函数和视图函数进行参数传递。(重点)
  • 2:能够在视图函数和自定义函数之间进行参数传递。
  • 3:每一次请求之后会清空钩子函数内部的值。(注意)

案例一:验证钩子函数可以和视图函数之间进行传递。

from flask import Flask ,g

app = Flask(__name__)

@app.before_request
def process_request():
	# 使用钩子函数保存
    g.username = 'renshanwen'


@app.route('/login')
def login():
	# 取除钩子函数的值
    print(g.username)
    return "hello"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

案例二:验证视图函数和自定义函数之间进行参数传递。

方案:自己定义一个函数,然后在视图函数中使用钩子函数保存数据,然后调用自定义函数,再在自定义函数中使用钩子获取值。

视图函数

from flask import Flask, make_response, Response, request, g

from home import test_demo

app = Flask(__name__)

@app.route('/login')
def login():
    g.name = 'renshanwen'
    test_demo()
    return "hello"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
#自定义函数
def test_demo():
    print(g.name)

运行结果:
在这里插入图片描述

四:综合认证:

1: 统一认证:

问题:我们所有的很多视图都需要获取登录身份,如果每个视图单独获取用户身份则会出现大量的代码冗余。
解决:在钩子函数中获取,在其他函数中直接使用。

from flask import Flask, session, g

app = Flask(__name__)
app.secret_key = 'test'

@app.before_request
def prepare():
    # 使用g变量来获取用户名
    g.name = session.get('username')


@app.route('/')
def index():
    # 直接拿过来使用
    if g.name:
        return "欢迎回来, %s" % g.name
    else:
        return '首页'
    
if __name__ == '__main__':
    app.run(debug=True)

2:反装饰:

链接地址

五:应用配置:

  • 1: 使用app.config配置字典添加配置信息[少量配置信息]
  • 2: 使用app.config.from_object从配置类中架子啊配置信息
  • 3: 使用app.config.from_envvar从环境变量中加载配置信息。

<案例一>:使用app.config配置。

app = Flask(__name__)

# 方案一:
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = "python39"
app.config['TESTING'] = True
app.config['LJSON_AS_ASCII'] = False

@app.route('/login')
def login():
    print(app.config['DEBUG'])
    print(current_app.config['DEBUG'])

    return "hello"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

<案例二>:使用app.config.from_object配置。
1: 新建一个配置文件settings:


# 创建一个配置基类
class BaseConfig(object):
    DEBUG =  True
    SECRET_KEY = "renshanwen"

class DevelopmentConfig(BaseConfig):
    DEBUG = True
    SQL_HOST = "127.0.0.1"
    SQL_PORT = 3306

class ProductionConfig(BaseConfig):
    DEBUG = False
    SQL_HOST = "192.168.22.11"
    SQL_PORT_MASTER = 3306
    SQL_PORT_SLAVE = 8306

2: 在配置文件中加载所在类的配置:

from flask import Flask,current_app
app = Flask(__name__)
app.config.from_object(DevelopmentConfig)

<三>在环境变量中加载配置:
1:在一个文件中写配置信息。
2:将文件路径添加进环境变量。
3:使用环境变量加载配置。

案例:
1:创建一个隐私配置文件:

# secret_config.py
SECRET_KEY = 'heima123'   # 隐私配置

2:配置环境变量:

 export ENV_CONFIG="/xx/secret_config.py"  # 设置隐私配置对应的环境变量

3:在main函数中使用:

# silent=True表示加载失败也不报错。
flask_app.config.from_envvar('ENV_CONFIG', silent=True)

六:工厂设计模式:

思路:我们可以将创建app设计为一个工厂类,我们传入不同的字段,给我们创建不同配置的app。
1: 在settings配置文件中暴露一个端口:核心代码是最后的字典。

# 创建一个配置基类
class BaseConfig(object):
    DEBUG =  True
    SECRET_KEY = "renshanwen"

class DevelopmentConfig(BaseConfig):
    DEBUG = True
    SQL_HOST = "127.0.0.1"
    SQL_PORT = 3306

class ProductionConfig(BaseConfig):
    DEBUG = False
    SQL_HOST = "192.168.22.11"
    SQL_PORT_MASTER = 3306
    SQL_PORT_SLAVE = 8306

config_dict = {
    "dev": DevelopmentConfig,
    "pro":ProductionConfig,
}

2:创建工厂类,并创建一个开发配置下的app。

from flask import Flask, make_response, Response, request
from settings import config_dict

def create_app(config_name):
    # 1: 创建app对象
    app = Flask(__name__)
    # 2:从配置类中加载配置信息
    config_class = config_dict[config_name]
    app.config.from_object(config_class)

    # 3: 从环境变量中加载配置信息
    app.config.from_envvar("CONFIG", silent=True)
    return app

app = create_app("dev")

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奈何碎银没有几两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值