# Flask框架之视图和路由

HelloWord程序

创建Python项目

  • 打开Pycharm,创建 pure Python类型的项目,创建项目完成之后选择之前创建的py3_flask作为虚拟环境

    《# Flask框架之视图和路由》 image.png

第四步路径可以通过在指定的虚拟环境下,输入 which python获得

示例

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


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

第一行:导入Flask类
第三行:Flask函数接收一个参数name,他会指向程序所在的包
第六行:装饰器的作用是将路由映射到试图函数hello_word
第十一、十二行: Flask应用程序实例的run方法,启动WEB服务器

在程序运行过程中,程序实例会使用url_map将装饰器路由和视图的对应关系保存起来

相关参数配置

在上一节实现了一个最简单的 Flask 应用程序,只使用了7行代码,接来对 Flask 程序的创建,运行配置做进一步的了解,具体有:

  • Flask 程序初始化参数
  • Flask 程序相关配置加载方式
  • app.run() 参数

初始化参数

Flask 程序实例在创建的时候,需要默认传入当前 Flask 程序所指定的包(模块),接下来就来详细查看一下 Flask 应用程序在创建的时候一些需要我们关注的参数:

《# Flask框架之视图和路由》 image.png

  • import_name
    • Flask程序所在的包(模块),传 name 就可以
    • 其可以决定 Flask 在访问静态文件时查找的路径
  • static_path
    • 静态文件访问路径(不推荐使用,使用 static_url_path 代替)
  • static_url_path
    • 静态文件访问路径,可以不传,默认为:/ + static_folder
  • static_folder
    • 静态文件存储的文件夹,可以不传,默认为 static
  • template_folder
    • 模板文件存储的文件夹,可以不传,默认为 templates

程序加载配置

在 Flask 程序运行的时候,可以给 Flask 设置相关配置,比如:配置 Debug 模式,配置数据库连接地址等等,设置 Flask 配置有以下三种方式:

  • 从配置对象中加载(常用)
    • app.config.from_object()
  • 从配置文件中加载
    • app.config.from_pyfile()
  • 从环境变量中加载(了解)
    • app.config.from_envvar()

使用方式

示例:

from flask import Flask


# 1.自定义项目配置类
class Config(object):
    '''flask项目的配置信息,以类属性的形式罗列即可'''
    DEBUG = True


app = Flask(__name__)

# 方式一:使用类的方式加载项目配置信息
# 2.加载配置类
# app.config.from_object(Config)
# 方式二:使用文件链接方式加载项目配置信息
# app.config.from_pyfile('config.ini')
# 方式三:使用环境变量方式
app.config.from_envvar('FLASKCONFIG')


# 常用的项目配置属性也会在App中保留一份


@app.route('/')
def hello_word():
    return 'Hello Word '


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

配置对象

  • 从配置对象中加载,创建配置的类,代码如下:
# 配置对象,里面定义需要给 APP 添加的一系列配置
class Config(object):
    DEBUG = True


# 创建 Flask 类的对象,指向程序所在的包的名称
app = Flask(__name__)

# 从配置对象中加载配置
app.config.from_object(Config)

运行测试,在修改代码后直接保存,会自动重启服务器

配置文件

  • 创建配置文件 config.ini,在配置文件中添加配置

    《# Flask框架之视图和路由》 image.png

  • 使用代码去加载配置

# 创建 Flask 类的对象,指向程序所在的包的名称
app = Flask(__name__)

# 从配置文件中加载配置
app.config.from_pyfile('config.ini')

环境变量(了解)

  • 编辑运行的相关配置

    《# Flask框架之视图和路由》 image.png
    《# Flask框架之视图和路由》 image.png

  • 使用代码去加载
# 创建 Flask 类的对象,指向程序所在的包的名称
app = Flask(__name__)
# 加载指定环境变量名称所对应的相关配置
app.config.from_envvar('FLASKCONFIG')

读取配置

  • app.config.get()
  • 在视图函数中使用 current_app.config.get()
@app.route('/')
def hello_word():

    # 获取属性值
    print(app.config['DEBUG'])
    # 当DEBUG写错时,显示后面的提示信息
    print(app.config.get('DEBUG','AA'))
    return 'Hello Word '

注:Flask 应用程序将一些常用的配置设置成了应用程序对象的属性,也可以通过属性直接设置/获取某些配置:app.debug = True

路由基本定义

  • 明确路由定义的参数,请求方式指定
  • PostMan使用

指定路由地址

# 指定访问路径为 demo1
@app.route('/demo1')
def demo1():
    return 'demo1'

给路由传参实列

有时我们需要将同一类URL映射到同一个视图函数处理,比如:使用同一个视图函数来显示不同用户的个人信息

# 路由传递参数
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %s' % user_id
  • 路由传递的参数默认当作string处理,也可以指定参数的类型
# 路由传递参数
@app.route('/user/<int:user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

这里指定int,尖括号中的内容是动态的,在此暂时可以理解为接受int类型的值,实际上int代表使用integerConverter去处理url传入的参数

指定请求方式

在Flask中,定义一个路由,默认的请求方式为:

  • GET
  • OPTIONS(自带)
  • HEAD(自带)
    如果想添加请求方式,那么可以如下指定
@app.route('/demo2', methods=['GET', 'POST'])
def demo2():
    # 直接从请求中取到请求方式并返回
    return request.method

完整代示例:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


# 127.0.0.1/demo1
@app.route('/demo1')
def demo1():
    return 'demo1'


# 给路由传参
# 127.0.0.1:5000/user/str数据类型
# <user_id>转换器提取url路径的参数
@app.route('/user/<user_id>')
def demo2(user_id):
    return 'user %s' % user_id


# 127.0.0.1:5000/user_int/int数据类型
@app.route('/user_int/<int:user_id>')
def demo3(user_id):
    return 'user %d' % user_id


if __name__ == '__main__':
    print(app.url_map)
    app.run(debug=True)
    

正则匹配路由

在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问

具体实现步骤为:

  • 导入转换器基类:在Flask中,所有的路由的匹配规则都是使用转换器独享记录
  • 自定义转换器:自定义类继承与转换器基类
  • 添加转换器到默认的转换器字典中
  • 使用自定义转化器实现自定义匹配规则

代码实现

  • 导入转换器基类
from werkzeug.routing import BaseConverter
  • 自定义转换器
# 自定义正则转换器
class RegexConverter(BaseConverter):
    def __init__(self, url_map, *args):
        super(RegexConverter, self).__init__(url_map)
        # 将接受的第1个参数当作匹配规则进行保存
        self.regex = args[0]
  • 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re
app = Flask(__name__)

# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter
  • 使用转换器去实现自定义匹配规则
    • 当前此处定义规则是:3位数字
@app.route('/user/<re("[0-9]{3}"):user_id>')
def user_info(user_id):
    return "user_id 为 %s" % user_id

运行测试:http://127.0.0.1:5000/user/123 ,如果访问的url不符合规则,会提示找不到页面

系统自带转换器

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

完整代码示例


from flask import Flask
# 导入转换器基类
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 1.自定义转换器类
class RegexConverter(BaseConverter):
    # 重写regex属性,当你将正则表达式传入给他的时候,BaseConVerter类处理
    def __init__(self, url_map, re):
        # 1.初始化父类的init方法,完成正则定义注册工作
        super(RegexConverter, self).__init__(url_map)
        # 2.初始化子类的init方法
        self.regex = re


# 2.注册正则匹配类
app.url_map.converters['re'] = RegexConverter


@app.route('/')
def hello_word():
    return 'Hello Word'


# 127.0.0.1:5000/user/123456
# 3.使用自定义正则转换器

@app.route('/user/<re("[0-9]{6}"):user_id>')
def demo1(user_id):
    return 'user %s' % user_id


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

获取请求参数

  • request:flask中代表当前请求的 request 对象
  • 作用:在视图函数中取出本次请求数据
  • 导入:from flask import request
    常用属性如下:
属性说明类型
data记录请求的数据,并转换为字符*
form记录请求中的表单数据MultiDict
args记录请求中的查询参数MultiDict
cookies记录请求中的cookie信息Dict
headers记录请求中的报文头EnvironHeaders
method记录请求使用的HTTP方法GET/POST
url记录请求的URL地址string
files记录请求上传的文件*

完整代码

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


'''
get: 获取服务器数据,问号后面携带的参数,告知服务器获取的数据
post: 往服务器新增数据,请求体里面携带的参数:一般是需要存到数据库的数据
'''


# 127.0.0.1:5000/get?user_name=curry&age=18
@app.route('/get')
def demo1():
    """提取get请求问号后面携带的参数"""
    # request.method   获取访问方式:后面字符串必须大写
    if request.method == 'GET':
        # 方式: request.method.args.get('key',"")
        user_name = request.args.get('user_name', '')
        age = request.args.get('age', '')
        return '%s %s' % (user_name, age)
    else:
        return '405请求方式不正确'


@app.route('/post', methods=['post'])
def demo2():
    '''提取post请求体中携带的参数'''
    if request.method == 'POST':
        # 方式
        user_name = request.form.get('user_name', '')
        user_id = request.form.get('user_id', '')
        return '%s %s' % (user_name, user_id)
    else:
        return '405请求方式不正确'

@app.route('/upload', methods=['post'])
def demo3():

    if request.method == 'POST':
        # 方式:request.files.get('key', '')
        file = request.files.get('pic', '')
        file.save('./1.jpg')
        return 'upload succes'
    else:
        return '405请求方式不正确'

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

构造响应数据

视图常用逻辑

  • 返回JSON
  • 重定向
    • Url_for
  • 自定义状态码

返回JSON

在使用Flask写一个接口时候需要给客户端返回JSON数据,在Flask中可以直接使用jsonify生成一个JSON的响应

# 返回JSON
@app.route('/demo3')
def demo3():
    json_dict = {
        "user_id": 10,
        "user_name": "laowang"
    }
    return jsonify(json_dict)

不推荐使用json.dumps转成JSON字符串直接返回,因为返回的数据要符合HTTP协议规范,如果是JSON需要指定content-type:application/json
完整代码:

from flask import Flask, jsonify
import json

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/json')
def demo1():
    '''json数据转换'''

    dict = {
        'name': 'james',
        'age': 34,
        'info': {
            'team': 'laker'
        }
    }
    # 序列化: 将python对象转换成json字符串
    json_str = json.dumps(dict)
    # 反序列化: 将json字符串转换成python对象
    my_json = json.loads(json_str)

    # 1.能将python对象转换成json字符串
    # 2.能将相应体数封装成响应对象并返回
    # 3.指明了响应数据格式: ContentType = 'application/json'
    my_jsons = jsonify(dict)
    return my_jsons
    # return json_str


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


重定向

  • 重定向到百度
# 重定向
@app.route('/demo4')
def demo4():
    return redirect('http://www.baidu.com')
  • 重定向到自己写的视图函数
    • 可以直接填写自己的Url路径
    • 也可以使用url_for生成指定试图函数所对应的url
@app.route('/demo1')
def demo1():
    return 'demo1'

# 重定向
@app.route('/demo4')
def demo4():
    return redirect(url_for('demo1'))
  • 重定向到带有参数的视图函数
    • 在url_for函数中传入参数
# 路由传递参数
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

# 重定向
@app.route('/demo4')
def demo4():
    # 使用 url_for 生成指定视图函数所对应的 url
    return redirect(url_for('user_info', user_id=100))

完整代码:

from flask import Flask, redirect, url_for

app = Flask(__name__)


@app.route('/index')
def hello_word():
    return 'Hello Word'


@app.route('/redirect')
def redirects():
    '''重定向到百度'''
    # 使用redirect方法进行重定向
    return redirect('http://www.baidu.com')


@app.route('/demo2')
def demo2():
    '''重定向到自身的根路径'''

    # url_for : url反向解析函数
    # 根据函数名称一一解析出对应的url
    return redirect(url_for('hello_word'))


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

自定义状态码

  • 在Flask中,可以很方便的返回自定义状态码,以实现不符合http协议的状态码,例如: status code:666
@app.route('/demo4')
def demo4():
    return '状态码为 666', 666

装饰器路由具体实现梳理

《# Flask框架之视图和路由》 image.png

  • Flask有两大核心:Werkzeug和Jinja2
    • Werkzeug实现路由\调试和web服务器网关接口
    • Jinja2实现了模板
  • Werkzeug是一个遵循WSGI协议的python函数库
    • 其内部实现了很多Web框架底层的东西,比如request和response对象;
    • 与WSGI规范的兼容;支持Unicode;
    • 支持基本的会话管理和签名Cookie;
    • 集成URL请求路由等。
  • Werkzeug库的 routing 模块负责实现 URL 解析。不同的 URL 对应不同的视图函数,routing模块会对请求信息的URL进行解析,匹配到URL对应的视图函数,执行该函数以此生成一个响应信息。

    routing模块内部有:

  • Rule类
    • 用来构造不同的URL模式的对象,路由URL规则
  • Map类
    • 存储所有的URL规则和一些配置参数
  • BaseConverter的子类
    • 负责定义匹配规则
  • MapAdapter类
    • 负责协调Rule做具体的匹配的工作

状态保持

  • 因为http是一种无状态协议,浏览器请求服务器是无状态的。
  • 无状态:指一次用户请求时,浏览器\服务器无法知道之前这个用户做过什么,每次请求都是新的请求
  • 无状态原因:浏览器与服务器之间是使用socket套接字进行通信,服务器将请求结果返回给浏览器之后,会关闭当前的socket连接,而且服务器也会在处理页面完毕之后销毁页面对象
  • 有时需要保持下来用户浏览的状态,比如用户是否登陆过,浏览过哪些商品等
  • 实现状态保存主要有两种方式
    • 在客户端保存用cookie
    • 在服务端保存用session

无状态协议

1.协议对于事务处理没有记忆能力
2.对同一个 url 请求没有上下文关系
3.每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
4.服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
5.人生若只如初见

Cookie

  • Cookie:指某些网站为了辨别用户身份、进行会话跟踪而储存在用户本地的数据(通常经过加密)。

    • 复数形式Cookies.
    • Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。
    • Cookie的key/value可以由服务器端自己定义。
  • 提示:

    • Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
      -Cookie基于域名安全,不同域名的Cookie是不能互相访问的
      • 如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到itcast.cn写的Cookie信息
      • 浏览器的同源策略
    • 当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息

设置cookie

from flask imoprt Flask,make_response
@app.route('/cookie')
def set_cookie():
    resp = make_response('this is to set cookie')
    resp.set_cookie('username', 'itcast')
    return resp

《# Flask框架之视图和路由》 image.png

设置过期时间

@app.route('/cookie')
def set_cookie():
    response = make_response('hello world')
    response.set_cookie('username', 'itheima', max_age=3600)
    return response

《# Flask框架之视图和路由》 image.png

获取cookie

from flask import Flask,request
#获取cookie
@app.route('/request')
def resp_cookie():
    resp = request.cookies.get('username')
    return resp

《# Flask框架之视图和路由》 image.png

完整代码:

from flask import Flask, make_response, request

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/login')
def login():
    '''登录成功后借助cookie保存登录信息'''
    # 1.创建响应对象
    response = make_response('login success')
    # 2.借助响应对象的set_cookie方法设置键值对
    '''
    参数1: key   参数2: value  参数3: max_age = 表示过期时长
    '''
    response.set_cookie('user_name', 'laowang', max_age=3600)
    response.set_cookie('user_id', '1', max_age=3600)

    return response


@app.route('/index')
def index():
    '''再次请求首页的时候,提起cookie中的用户信息'''
    user_name = request.cookies.get('user_name', '')
    user_id = request.cookies.get('user_id', '')

    return 'index %s  --  %s' % (user_name, user_id)


@app.route('/login_out')
def loginout():
    '''退出登录删除cookie中用户数据'''
    # 1.构建响应对象
    respone = make_response('login out delete')
    # 2.利用响应对象中的delete_cookie方法删除对应的cookie
    respone.delete_cookie('user_name')
    respone.delete_cookie('user_id')
    return respone


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

Session

  • 对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息
  • 在服务器端进行状态保持的方案就是Session
  • Session依赖于Cookie

session数据的获取

session:请求上下文对象,用于处理HTTP请求中的一些数据内容

@app.route('/set_session')
def set_session():
    session['username'] = 'itcast'
    return 'set_session ok!'

@app.route('/get_session')
def get_session():
    return session.get('username')

记得设置secret_key: app.secret_key = ‘password’ 的作用
https://segmentfault.com/q/1010000007295395

完整代码:

from flask import Flask, session

app = Flask(__name__)

# 加密
app.secret_key = 'asdfghjkl'


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/login')
def login():
    '''登录成功借助cookie储存用户登录信息到服务器'''
    # session 会将用户数据存储到服务器中,一般是数据库
    session['user_name'] = 'laosong'
    session['user_id'] = '1'
    return 'login sucess'


@app.route('/index')
def index():
    '''再次请求首页的时候可以借助session提取用户的登录信息'''
    user_name = session.get('user_name')
    user_id = session.get('user_id')

    return 'user_name : %s, user_id : %s' % (user_name, user_id)


@app.route('/out')
def login_out():
    '''退出后删除'''
    session.pop('user_name', '')
    session.pop('user_id', '')
    return 'out susser'


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


请求钩子

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:

  • 在请求开始时,建立数据库连接;
  • 在请求开始时,根据需求进行权限校验;
  • 在请求结束时,指定数据的交互格式;

为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。

请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:

  • before_first_request
    • 在处理第一个请求前执行
  • before_request
    • 在每次请求前执行
    • 如果在某修饰的函数中返回了一个响应,视图函数将不再被调用
  • after_request
    • 如果没有抛出错误,在每次请求后执行
    • 接受一个参数:视图函数作出的响应
    • 在此函数中可以对响应值在返回之前做最后一步修改处理
    • 需要将参数中的响应在此参数中进行返回
  • teardown_request:
    • 在每次请求后执行
    • 接受一个参数:错误信息,如果有相关错误抛出

完整代码:

from flask import Flask
from flask import abort

app = Flask(__name__)


# 在第一次请求之前调用,可以在此方法内部做一些初始化操作
@app.before_first_request
def before_first_request():
    print("before_first_request")


# 在每一次请求之前调用,这时候已经有请求了,可能在这个方法里面做请求的校验
# 如果请求的校验不成功,可以直接在此方法中进行响应,直接return之后那么就不会执行视图函数
@app.before_request
def before_request():
    print("before_request")
    # if 请求不符合条件:
    #     return "laowang"


# 在执行完视图函数之后会调用,并且会把视图函数所生成的响应传入,可以在此方法中对响应做最后一步统一的处理
@app.after_request
def after_request(response):
    print("after_request")
    response.headers["Content-Type"] = "application/json"
    return response


# 请每一次请求之后都会调用,会接受一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(e):
    print("teardown_request")


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

if __name__ == '__main__':
    app.run(debug=True)
  • 在第一次请求时打印

before_first_request
before_request
after_request
teardown_request

  • 在第二次请求时打印

before_request
after_request
teardown_request

异常捕获

HTTP异常主动抛出

  • abort 方法
    • 抛出一个给定状态的HTTPException 或者 指定响应, 例如想要用一个页面未找到异常来终止请求,可以调用abort(404)
  • 参数
    • code-HTTP的错误状态码(必须)
# abort(404)
abort(500)

抛出状态码的话,只能抛出 HTTP 协议的错误状态码

捕获错误

  • errorhandler装饰器
    • 注册一个错误处理程序,当程序抛出指定错误状态码的时候,就会调用该装饰器所装饰的方法
  • 参数
    • code_or_exception-HTTP的错误状态码或指定异常
  • 例如统一处理状态码为500的错误给用户友好提示:
@app.errorhandler(500)
def internal_server_error(e):
    return '服务器搬家了'
  • 捕获指定异常
@app.errorhandler(ZeroDivisionError)
def zero_division_error(e):
    return '除数不能为0'

完整代码:

from flask import Flask, redirect, abort

app = Flask(__name__)


@app.route('/')
def hello_word():
    # 定义两个错误
    # a = 1/0
    # abort 指定错误
    abort(404)
    return 'Hello Word'


@app.errorhandler(404)
def handler(e):
    '''404'''
    print(e)
    # 重定向
    return redirect('http://hd.mi.com/webfile/zt/hd/2014042802/cn.html')


@app.errorhandler(ZeroDivisionError)
def error(a):
    '''捕获异常'''
    return '不能除零'


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

上下文

上下文:即语境,语意,在程序中可以理解为在代码执行到某一时刻时,根据之前代码所做的操作以及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情。

Flask中有两种上下文,请求上下文和应用上下文

Flask中上下文对象:相当于一个容器,保存了 Flask 程序运行过程中的一些信息。

请求上下文(request context)

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

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

应用上下文(application context)

它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。

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

current_app

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

  • 应用的启动脚本是哪个文件,启动时指定了哪些参数
  • 加载了哪些配置文件,导入了哪些配置
  • 连了哪个数据库
  • 有哪些public的工具类、常量
  • 应用跑再哪个机器上,IP多少,内存多大
current_app.name
current_app.test_value='value'

g变量

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

g.name='abc'

不同的请求,会有不同的全局变量

两者区别:

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

上下文中的对象只能在指定上下文中使用,超出范围不能使用 请求上下文和应用上下文原理实现:https://segmentfault.com/a/1190000004223296

完整代码

from flask import Flask, request, session, current_app, g

app = Flask(__name__)

app.secret_key = 'asdfghjkl'


@app.route('/')
def hello_word():

    # 请求上下文
    print(request.method)
    print(request.url)
    session['user_name'] = 'curry'
    print(session.get('user_name', ''))

    # 应用上下文
    current_app.config.get("DEBUG")
    g.user = 'James'
    print(g.user)

    return 'Hello Word'


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

Flask-script扩展

通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过:

python hello.py runserver -host ip地址
以上代码告诉服务器在哪个网络接口监听来自客户端的连接。默认情况下,服务器只监听来自服务器所在的计算机发起的连接,即localhost连接。

我们可以通过python hello.py runserver –help来查看参数。

《# Flask框架之视图和路由》 image.png

代码实现

  • 安装Flask-Script

pip install flask-script

  • 集成Flask-Script
from flask import Flask
from flask_script import Manager

app = Flask(__name__)
# 把 Manager 类和应用程序实例进行关联
manager = Manager(app)

@app.route('/')
def index():
    return '床前明月光'

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

Flask-Script 还可以为当前应用程序添加脚本命令,后续项目中会使用到

    原文作者:懵懂_傻孩纸
    原文地址: https://www.jianshu.com/p/39b64c406bff
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞