flask_上下文处理_flask脚手架

context

什么是上下文

日常生活中的上下文:

从一篇文章中抽取一段话,你阅读后,可能依旧无法理解这段话中想表达的内容,因为它引用了文章其他部分的观点,要理解这段话,需要先阅读理解这些观点。 这些散落于文章的观点就是这段话的上下文。

对Flask框架来说就是:

Flask从客户端收到请求的时候,视图函数如果要处理请求的话,可能需要访问/使用一些对象。那么这些对象可以通过参数的形式传递进来,或者在函数中通过访问外部变量来用。
这个外部变量要有特定的值才会有意义,那么这些有特定值或者特定意义的外部变量的集合就是上下文

例子:

from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def index():
    user_agent = request.headers.get('User-Agent')
    return 'Your brower is %s' % user_agent
if __name__ == '__main__':
    app.run()

这里的request变量就是请求上下文,也就是当请求被推送之后,request才有意义,接下来才可以用request。

Flask 上下文作用

例如:Flask 的视图函数被使用的时候是需要知道前端请求的 url、请求参数等应用信息才可以正常运行,那么要怎么设计实现呢?

Flask 为此设计出了自己的上下文机制,当在特定场景下需要使用请求信息时,直接 from flask import request就可以获得当前请求的所有信息并且在多线程环境下是线程安全的。

总结

Flask中上下文对象:相当于一个容器,保存了 Flask 程序运行过程中的一些信息[变量、函数、类与对象等信息]。

Flask中有两种上下文,请求上下文(request context)和应用上下文(application context)。

请求上下文(request context)

请求上下文提供的变量/属性/方法/函数/类与对象,只能在视图中或者被视图调用的地方使用。

思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等

在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session

  • request
    • 封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。
  • session
    • 用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。

请求上下文提供的变量/属性/方法/函数/类与对象,只能在视图中或者被视图调用的地方使用

应用上下文(application context)

应用上下文它不是一直存在的,它只是请求上下文中的一个对app的代理,所谓的local proxy。它的作用主要是帮助request获取当前的应用,它是伴request而生,随request而灭的。

应用上下文提供给我们使用的变量,也是只能在视图或者被视图调用的地方进行使用

应用上下文对象有:current_app,g

current_app

应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:

  • 应用的启动脚本是哪个文件,启动时指定了哪些参数
  • 加载了哪些配置文件,导入了哪些配置
  • 连接了哪个数据库
  • 有哪些可以调用的工具类、常量
  • 当前flask应用在哪个机器上,哪个IP上运行,内存多大
from flask import Flask,request,session,current_app,g
# 初始化
app = Flask(import_name=__name__)
# 声明和加载配置
class Config():
    DEBUG = True
app.config.from_object(Config)
# 编写路由视图
@app.route(rule='/')
def index():
    # 应用上下文提供给我们使用的变量,也是只能在视图或者被视图调用的地方进行使用,
    # 但是应用上下文的所有数据来源于于app,每个视图中的应用上下文基本一样
    print(current_app.config)   # 获取当前项目的所有配置信息
    print(current_app.url_map)  # 获取当前项目的所有路由信息
    return "<h1>hello world!</h1>"

if __name__ == '__main__':
    # 运行flask
    app.run(host="0.0.0.0")

g变量

g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别

g.name='abc' # name是举例,实际要保存什么数据到g变量中,可以根据业务而定,你可以任意的数据进去

注意:不同的请求,会有不同的全局变量g

from flask import Flask,request,session,current_app,g
# 初始化
app = Flask(import_name=__name__)
# 声明和加载配置
class Config():
    DEBUG = True
app.config.from_object(Config)
@app.before_request
def before_request():
    g.name = "root"

def get_func():
    name = g.name
    print("g.name=%s" % name)

# 编写路由视图
@app.route(rule='/')
def index():
    get_func()
    return "<h1>hello world!</h1>"


if __name__ == '__main__':
    # 运行flask
    app.run(host="0.0.0.0")

两者区别:

  • 请求上下文:保存了客户端和服务器交互的数据,一般来自于客户端。
  • 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如路由列表,程序名、数据库连接、应用信息等

Flask-Script 扩展(终端脚本工具)

这个模块的作用可以让我们通过终端来控制flask项目的运行,类似于django的manage.py

安装命令:

pip install flask-script

集成 flask-script到flask应用中,创建一个主应用程序,一般我们叫manage.py/run.py/main.py都行。

from flask import Flask

app = Flask(__name__)

"""使用flask_script启动项目"""
from flask_script import Manager
manage = Manager(app)

@app.route('/')
def index():
    return 'hello world'

if __name__ == "__main__":
    manager.run()

启动终端脚本运行项目的命令:

# 端口和域名不写,默认为127.0.0.1:5000
python run.py runserver

# 通过-h设置启动域名,-p设置启动端口
python run.py runserver -h127.0.0.1 -p8888

Flask-Script 还可以为当前应用程序添加脚本命令

1. 引入Command命令基类
2. 创建命令类必须直接或间接继承Command,并在内部实现run方法,同时如果有自定义的其他参数,则必须实现__init__
3. 使用flask_script应用对象manage.add_command对命令类进行注册,并设置调用终端别名。
#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from flask import Flask
from flask_script import Command,Option,Manager
app = Flask(__name__)
class Config():
    DEBUG = True
app.config.from_object(Config)

class HelloCommand(Command):
    def run(self):
        print('命令执行了......')
manager = Manager(app)
manager.add_command('hello',HelloCommand)

@app.route('/')
def index():
    return 'ok'
if __name__ == "__main__":
    manager.run()

终端:python app03.py hello

接收指定的指令参数

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from flask import Flask
from flask_script import Command,Option,Manager
app = Flask(__name__)
class HelloCommand(Command):
    option_list = [
        #参数1:作为run接受的参数名称,指定的参数名称,参数2:辅助参数名称
        Option('--name','-n',help='xxx'),
        Option('--num','-m')#多个指令参数
    ]
    def run(self,name,num): #run必须使用参数接受命令参数值
        print(name,num)
        print('命令执行了......')
manager = Manager(app)
manager.add_command('hello',HelloCommand)

@app.route('/')
def index():
    return 'ok'
if __name__ == "__main__":
    manager.run()

终端指令:python app03.py hello -n='bobo',python app03.py hello -m=20

创建子应用目录结构:flask的应用其实叫做蓝图(创建一个users的目录,里面存储三个源文件)

from flask import Flask
from flask_script import Manager, Command, Option
app = Flask(__name__)
class Config():
    DEBUG = True
app.config.from_object(Config)
manager = Manager(app)
import os
class BluePrintCommand(Command):
    option_list = [
        Option("--name","-n",help="蓝图名称")
    ]

    def run(self,name=None):
        if name is None:
            print("蓝图名称不能为空!")
            return
        if not os.path.isdir(name):
            os.mkdir(name)
        open("%s/views.py" % name,"w")
        open("%s/models.py" % name,"w")
        with open("%s/urls.py" % name,"w") as f:
            f.write("""from . import views
urlpatterns = [

]
""")

manager.add_command("blue", BluePrintCommand)

@app.route("/")
def index():
    return "ok"

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

终端指令:python app03.py blue --name=users

posted @ 2021-02-10 14:08  死里学  阅读(182)  评论(0)    收藏  举报