Python框架之flask

Python框架之flak

  • 1.目标
  • 2.Flask初识
  • 3.工程搭建
  • 4.参数说明
  • 5.路由与蓝图
  • 6.处理请求
  • 7. 处理响应
  • 8.Cookie和Session
  • 9.异常处理
  • 10.请求钩子
  • 11.上下文
  • 12.上下文综合应用
  • 13.独立使用flask上下文方式
  • 14.上下文实现原理
  • 15.定制返回JSON格式

1.目标

  1. 为什么学习框架?
  2. IT哲学-挨踢哲学
    1. 现有问题/需求,再有解决工具,工具是为解决问题/需求而诞生的
    2. 故学习重点是探究问题的本质,及解决问题的思路和思想
    3. 可能没有最好的工具,只有更合适的工具
  3. 学习目标
    1. 明确问题/需求及其背景(即工具的应用场景)
    2. 理解并掌握解决问题的思路
    3. 理解后熟练工具
  4. 学习方法
    1. 不机械的抄代码,背代码,锻炼自己写代码的能力
    2. 先思考,在动手
    3. 先想清楚问题是什么,在想请解决问题思路,最后动手将思路实现
    4. 多思考,勤动手,多问自己为什么,多提出不同的解决方式在动手验证可行性,多调bug
  5. 框架的学习目标
    1. 如何编写视图
    2. 如何处理请求
    3. 如何构造响应

2.Flask初识

flask 诞生于2010年,是Armin ronacher用python语言基于Werkzeug工具箱编写的轻量级web开发框架
Flask本身相当于一个内核,其他几乎所有功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用到第三方的扩展来实现。比如可以用Flask扩展加入ORM,窗体验证工具,文件上传,身份验证等。Flask没有默认使用的数据库,可以选择Mysql,也可以使用NoSQL.
其WSGI工具箱采用Werkzeug(路由模块),模板引擎则使用Jinja2,这两个也是Flask框架的核心

  1. 框架对比
    1. 框架轻重
      1. 重量级框架:为方便业务程序的开发,提供了丰富的工具,组件如Django
      2. 轻量级框架:只提供web框架的核心功能,自由,灵活,高度定制,如Flask,Tronado
    2. 与Django对比
      1. Django提供了(Flask都没有):
        1. django-admin快创建项目工程目录
        2. manage-py 管理项目工程
        3. orm模型(数据库抽象层)
        4. admin后台管理站点
        5. 缓存机制
        6. 文件存储系统
        7. 用户认证系统
    3. Flask常用扩展包
      1. 扩展列表
      2. Flask-SQLalchemy:操作数据库
      3. Flask-script:插入脚本
      4. Flask-migrate:管理迁移数据库
      5. Flask-Session:Session存储方式指定
      6. Flask-WTF:表单
      7. Flask-Mail:邮件;
      8. Flak-Bable:提供国际化和本地化支持,翻译
      9. Flask-Login:认证用户的状态
      10. Flask-OpenID:认证
      11. Flask-RESTful:开发REST API的工具
      12. Flask-Bootstrap:集成前端Twitter Bootstrap框架
      13. Flask-Moment:本地化日期和时间
      14. Flask-Admin:简单而可扩展的管理接口的框架
    4. 框架选择
      1. 自由、灵活、高度定制–》flask
      2. 快速实现业务,不考虑技术类型,越简单直接越好–》Django

3.工程搭建

  1. 环境安装
    1. 虚拟环境和pip命令
      1. 虚拟环境(virtualenv)
        1. mkvirtualen 创建虚拟环境
        2. rmvirtualenv 删除虚拟环境
        3. workon +虚拟环境名 (空格 tab两次查看)进入到虚拟环境,查看所有虚拟环境
        4. deactivate 退出虚拟环境
      2. pip
        1. pip install 安装依赖包
        2. pip uninstall 卸载依赖包
        3. pip list 查看已安装的依赖包
        4. pip freeze 冻结当前环境的依赖包
      3. 没有virtualenv的需安装
        1. sudo apt-get install python3-virtualenv
    2. 创建虚拟环境需要联网
      1. mkvirtualenv flask -p /usr/bin/python3
    3. 安装flask pip install flask
  2. flask程序编写
    1. 创建hellow.py文件
#导入Flask类
from flask import Flask
#Flask类接收一个参数__name__
app=Flask(__name__)
#装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
return' hello_world'
#Flask应用程序实例的run方法启动WEB服务器
if __name__=='__main__':
	app.run()
  1. 启动 python helloworld.py

4.参数说明

Flask对象的初始化参数
应用程序的配置参数
app.run() 运行参数

  1. Flask对象初始化参数
    1. Flask程序实例在创建的时候,需要默认传入当前的Flask程序指定的包(模块),
    2. import_name
      1. Flask程序所在的包(模块),传__name__就可以
      2. 其可以决定Flask在访问静态文件时查找的路径
    3. static_url_path
      1. 静态文件访问路径,可以不传,默认为:/+static_folder
    4. static_folder
      1. 静态文件存储的文件夹,可以不传,默认为 static
    5. template_folder
      1. 模板文件存储的文件夹,可以不传,默认为 templates
  2. 应用程序的配置参数
    1. 对于Flask对象初始化参数仅仅设置的是Flask本身的属性,如“
    2. Flask从哪里读取静态文件 Flask从哪里读取模板文件 等等
    3. 应用程序配置参数设置的是一个web应用工程的相关信息如:
      1. 数据库的连接信息
      2. 日志的配置信息
      3. 自定义的配置信息
    4. 作用:集中管理项目的所有配置信息
    5. 使用方式:
      1. Django将所有配置信息都放到settings.py文件中,而Flask则不同
      2. Flask将配置信息保存到了app.config属性中,该属性可以按照字典类型进行操作
      3. 读取: app.confiig.get(name) app.config(name)
    6. 设置 主要使用三种方式:
      1. 从配置对象中加载 app.config.from_object(配置对象)
        1. 优点:
          1. 可继承–复用
        2. 缺点:
          1. 敏感数据暴露
        3. 应用场景:
          1. 默认配置
      2. 从配置文件中加载: app.config.from_pyfile(配置文件)
        1. 优点:
          1. 独立文件–可提取(保护敏感数据)
        2. 缺点:
          1. 不可继承
          2. 文件路径固定,不灵活
        3. 应用场景:
          1. 不考虑灵活性,只考虑敏感度
      3. 从环境变量中加载
        1. 环境变量一般是指操作系统中用来指定操作系统运行环境的一些参数,如临时文件夹位置和系统文件夹位置等,环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或多个应用程序所将使用到的信息

        2. 通俗理解就是,环境变量就是我们设置在操作系统中,由操作系统代为保存的变量值

        3. 在linux系统中设置和读取环境变量的方式如下:

          1. export 变量名=变量值 #设置
          2. echo $变量名 #读取
        4. 在终端设置的环境变量在pycharm中启动不起作用,原因是终端与pycharm是两个不同的环境

        5. 优点:

          1. 独立文件
          2. 保护敏感数据
          3. 文件路径不固定,灵活
        6. 缺点:

          1. 不方便,要设置环境变量
        7. 项目中常用的方式

          1. 使用工厂模式创建Flask app,并结合使用配置对象与环境变量加载配置
          2. 使用环境变量加载不想出现在代码中的敏感配置信息
          3. 同名变量,后面的会覆盖前面的
#应用程序的配置参数
"""
#1.配置对象方式加载配置信息
# class DefaultConfig(object):
#     '''默认配置'''
#     SECRET_KEY='fdkasfjowq'
#2.从配置文件中加载 setting.py
#3.从环境变量中加载配置文件
"""
app=Flask(__name__,static_url_path='/s',static_folder='static_files')
#设置
# app.config.from_object(DefaultConfig)
# app.config.from_pyfile('setting.py')
app.config.from_envvar('PROJECT_SETTING',silent=True)
#silent 表示系统环境变量中没有设置相应值时是否抛出异常
# 	False 表示不安静处理,没有值时报错通知,默认为False
# 	True  表示安静处理,即没有值也让Flask正常的运行
#终端:export PROJECT_SETTING=setting.py
#定义视图
@app.route('/')
def index():
    #读取配置信息
    print(app.config['SECRET_KEY'])
    return '百度'
#动态路由
"""
@app.route('/user/')
def user(name):
    return 'hello %s'%name
"""
if __name__ == '__main__':
    app.run()
  1. app.run() 参数
    1. 可以指定运行的主机ip地址,端口,是否开启调试模式
    2. app.run(host='ip地址‘,port='端口号’,debug=True)
    3. 关于DEBUG调试模式
      1. 程序代码修改后可以自动重启服务器
      2. 在服务器出现相关错误时可以直接将错误信息返回到前端进行展示
  2. 开发服务器启动方式
    1. 在1.0版本后,由代码编写的app.run()语句调整为命令 flask.run
    2. 终端启动(要设置需要的环境变量):
      1. linux
        1. export FLASK_APP=flaskProject
        2. flask run
      2. windows:
        1. set FLASK_APP=flaskProject/app.py
        2. flask run
      3. 说明:
        1. 环境变量 FLASK_APP 指明flask 的启动实例
        2. 绑定地址 端口 flask run -h ip地址 -p 端口号
        3. flask run --help 获取帮助
        4. 生产模式与开发模式的控制
          1. 通过FLASK_ENV 环境变量指明
          2. export FLASK_ENV=production 运行在生产模式,未指明则默认为此方式
          3. export FLASK_ENV=development 运行在开发模式
    3. pycharm中运行新式flask
      1. 新版:换成model模式,设置Target为项目路径
        Python框架之flask_第1张图片

      2. 旧版

        1. flask run<==>python -m falsk run
        2. 设置Parameters 为 -m falsk run

5.路由与蓝图

  1. 查询路由信息
    1. 命令行方式: flask routes
    2. 在程序中获取:
      1. print(app.url_map)
      2. 在程序中遍历路由信息:
        1. from rule in app.url_map.iter_rules():
          . print(‘name={},path={}’.format(rule.endpoint,rule.rule))
    3. 通过访问 / 地址 ,以json的方式返回应用内的所有路由信息
# 遍历路由信息
# for rule in app.url_map.iter_rules():
#     print('name={},path={}'.format(rule.endpoint, rule.rule))
# print(list(app.url_map.iter_rules()))# 
# [ index>, ' (HEAD, GET, OPTIONS) -> static>]
# print(app.url_map)

#通过访问 / 地址,以json的方式返回应用内的所有路由信息
@app.route('/')
def route_app():
    '''主视图,返回所有视图网址'''
    rules_iterator=app.url_map.iter_rules()
    return json.dumps({rule.endpoint:rule.rule for rule in rules_iterator})# {"route_app": "/", "static": "/s/"}
  1. 指定请求方式
    1. 在flask中,定义路由默认的请求方式为:
      1. GET
      2. OPTIONS(自带)–简化版的GET请求,用于询问服务器接口信息的,如接口允许的请求方式,允许的请求源头
      3. HEAD(自带)–简化版的GET请求 只返回GET请求处理的响应头,不返回响应体
      4. CORS 跨域 django-cors进行了中间件拦截处理了options请求
        1. 前端访问接口–option 进行请求询问是否允许–返回response 询问结果-- GET请求资源
      5. 自定义 POST PUT DELETE PATCH
    2. 利用methods 参数可以指定一个接口的请求方式
  2. 蓝图
    1. 初识
      1. 一个蓝图就是一个子应用
      2. 在flask应用项目中,使用蓝图Blueprint来分模块组织管理
      3. 蓝图实际 可以理解为一个存储一组视图方法的容器对象,特点:
        1. 一个应用可以有多个蓝图
        2. 可以将一个Blueprint注册到任何一个未使用的URL下 如:‘/use’
        3. Blueprint可以单独具有自己的模板,静态文件或者其他通用操作方法,它并不是必须要实现应用的视图和函数
        4. 一个应用初始化时,就应该要注册需要使用的Blueprint
        5. 一个Blueprint并不是一个完整的应用,不能独立于应用运行,而必须要注册到一个应用中
    2. 应用蓝图
      1. 创建一个蓝图对象
        1. user_bp=Blueprint(‘user’,name)
      2. 在蓝图上进行操作,注册路由,指定静态文件夹,注册模板过滤器

#蓝图的应用
#单个文件
"""
#1.创建蓝图对象
user_bp=Blueprint('user',__name__)
#2在蓝图上操作,注册路由,指定静态文件夹,注册模板过滤器
@user_bp.route('/')
def user_profile():
    return 'user_profile'
#3.在应用对象上注册这个蓝图
app.register_blueprint(user_bp)
"""
#目录中使用
""""""
#1.创建python包--在__init__文件中创建蓝图对象
#2.创建视图文件 在视图文件中操作
#3.在应用上注册这个蓝图 使用prefix给路由加前缀 先指定前缀再指定路由 访问时前缀可为空
from goods import good_bp
app.register_blueprint(good_bp)


  1. 蓝图内部的静态文件
    1. 和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由,需要在创建时指定static_folder 参数
#将蓝图目录下的static_admin目录设为静态目录
admin=Blueprint('admin',__name__,static_folder='static_admin')
app.register_blueprint(admin,url_prefix='admin')
#使用/admin/static_admin/访问static_admin目录下的静态文件,也可通过static_url_path改变路径
admin=Blueprint('admin',__name__,static_folder='static_admin',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')
#蓝图内部的模板目录
admin=Blueprint('admin',template_folder='my_templates')
  1. Flask Debug模式的作用
    1. 后端出现错误,会返回真实的错误信息给前端
    2. 修改代码后,自动重启开发服务器
    3. 支持options请求不等价于实现了CORS跨域解决方案

6.处理请求

  1. 需求,在视图编写中需要读取客户端携带的数据时,如何才能正确的取出数据?
    1. 请求携带的数据可能出现在HTTP报文中的不同位置,需要使用不同的方法来获取参数
  2. URL路径参数(动态路由)
    1. 例:有一个请求访问的接口地址为user/123,其中123实际上为具体的请求参数,表明请求123号用户的信息,此时如何从url中提取123的数据?
      1. Flask不同与Django直接定义路由时编写正则表达式的方式,而是采用转换器语法:
      2. 此处的《》既是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配,并以字符串为数据类型,name为参数名传入视图,若匹配不到会返回404,如int不能匹配111sss
@app.route('/user/')#等价于@app.route('/user/')
def user(name):
    return 'hello %s'%name
  1. 转换器的使用
    1. DEFAULT_CONVERTERS={
      1. ’default’: UnicodeConverter,
      2. ’string’: UnicodeConverter,
      3. ’any’:AnyConverter,
      4. ’path’:PathConverter,
      5. ’int’:ItegerConverter,
      6. ’float’:FloatConverter,
      7. ’unid’:UNNIDCONcerter,
      8. }
    2. 自定义转换器
      1. 自定义转换器的类
      2. 将自定义转换器告知Flask应用
      3. 在使用转换器的地址定义使用
from werkzeug.routing import BaseConverter
#**加粗样式**1.自定义转换器类(需要导入werkzeug.routing /BaseConverter)
class MobileConverter(BaseConverter):
    '''手机号格式'''
    regex=r'1[3-9]\d{9}'#regex是固定的 正则表达式
#2.将自定义的转换器告知Flask应用
#将自定义的转换器添加到转换器字典中,并指定转换器使用时的名字为:mobile
app.url_map.converters['mobile']=MobileConverter
#3.在使用转换器的地方定义使用
@app.route('/user/')
def sen_code(mob_num):
    return 'send_code{}'.format(mob_num)
  1. 其他参数
    1. 若想获得其他地方传递的参数,可以通过Flask提供的request对象来读取。
    2. 不同位置的参数都放在request的不同属性中
    3. 属性–说明–类型
      1. data --记录请求的数据,并转换为字符串–*
      2. form–记录请求中的表单数据–MultilDct
      3. args–记录请求中的查询参数–MultiDict
      4. cookies–记录请求中的cookie信息–Dict
      5. headers–记录请求中的报文头–EnvironHeaders
      6. method–记录请求使用的HTTP方法–GET/POST
      7. url–记录请求的URL地址–string
      8. files–记录请求上传的文件–*
#其他参数request 需要导入request
#若想获得请求/articles?channel_id=1中channel_id的参数,可以按如下方式使用:
@app.route('/articles')
def get_articles():
    channel_id=request.args.get('channel_id')
    return 'get articles or channel {}'.format(channel_id)
  1. 上传图片
    1. 客户端上传图片到服务器,并保存到服务器中
#上传图片 客户端上传图片到服务器并保存到服务器中
@app.route('/upload',methods=['POST'])
def upload_file():
    f=request.files('images')
    #with open('./demo.png','wb')as new_file:
        #new_file.write(f.read())
    f.save('./demo.png')
    return 'ok'

7. 处理响应

  1. 需求—如何在不同的场景中返回响应信息?
  2. 返回模板
    1. 使用render_template 方法渲染模板并返回
#响应模板的渲染 render_template
@app.route('/index2')
def home():
    # mint=123
    # mstr='itcast'
    data=dict(
        my_str='fsfs',
        my_int=432
    )
    # return render_template('index2.html',my_str=mstr,my_int=mint)
    # return render_template('index2.html',my_str='intste',my_int=232)
    return render_template('index2.html',**data)
  1. 重定向与json
    1. return json.dumps() 不会设置响应头
    2. return jsonify
      1. 转换成json格式字符串
      2. 设置响应头Content-Type:application/json
#重定向 需要导入redirect
"""
@app.route('/demo2')
def demo2():
    return redirect('http://www.baidu.com')
"""
#返回JSON 需要导入jsonify
@app.route('/demo3')
def demo3():
    json_dict={
        'user_id':10,
        'user_name':'laowang'
    }
    return jsonify(json_dict)
  1. 自定义状态码与响应头
    1. 元组方式
      1. 可以返回一个元组,这样的元组必须是(response,status,headers)的形式,且至少包含一个元素,status值会覆盖状态码,headers可以是一个列表或字典,作为额外的消息标头值
    2. make_response
#自定义状态码与响应头
#元组方式
"""
@app.route('/demo4')
def demo4():
    # return '状态码为666',666  #响应体 状态码 响应头 省略时只能从右边省略
    # return '状态码 666',666,[('Itcast','Python')]
    return '状态码为666',666,{'Itcast':'Python'}
"""
#2.make_response方式
@app.route('/demo5')
def demo5():
    resp=make_response('make_response测试')
    resp.headers['Itcast']='Python'
    resp.status='404 Not Found'
    return resp

8.Cookie和Session

  1. Cookie
#Cookie设置 只在响应对象中设置
"""
@app.route('/cookie')
def s_cookie():
    resp=make_response('set cookie ok')
    resp.set_cookie('username','itcast',max_age=3600)# cookie名字 cookie的值 max_age(可选参数)设置有效期
    return resp
"""
#Cookie读取 需要导入request
"""
@app.route('/getcookie')
def get_cookie():
    resp=request.cookies.get('username')
    return resp
"""
#Cookie删除
"""
@app.route('/deletecookie')
def delete_cookie():
    resp=make_response('delete cookie')
    resp.delete_cookie('username')
    return resp
"""
  1. Session
    1. 需要先设置SECRET_KEY
    2. flask将session数据保存在哪?
      1. flask是浏览器session,将数据放在浏览器缓存
      2. SETRET_KEY相当于签名,保证session数据的安全性
#Session 需要先设置SECRET_KEY
class DefaultConfig(object):
    SECRET_KEY='gfsgsg'
app.config.from_object(DefaultConfig)#app.secret_key='ghkggjk'
# Session设置 需要先导包session
@app.route('/setsession')
def set_session():
    session['username']='itcast'#以字典形式设置保存
    return 'set session OK'
#读取
@app.route('/getsession')
def get_session():
    username=session.get('username')
    return 'get session username{}'.format(username)

9.异常处理

  1. HTTP异常主动抛出
    1. abort 方法(终止请求返回异常)
      1. 抛出一个给定状态码的HTTPException 或者 指定响应,如想要一个页面找到异常来终止请求,可以使用abort(404)
      2. 参数 code-HTTP的错误状态码
      3. abort(404) / abort(500)
      4. 抛出状态码时,只能抛出HTTP协议的错误状态码
    2. 捕获错误
      1. errorhandler装饰器
        1. 注册一个错误处理程序,当程序抛出指定错误状态码时,就会调用该装饰器所装饰的方法
      2. 参数:
        1. code_or_exception-HTTP的错误状态码或指定异常
        2. 例如:统一处理状态码为500的错误给用户友好的请求

10.请求钩子

启动中间件/中间层的作用
请求处理过程: pre_process—>view----->after process
request 请求处理流程:
middleware1.pre_process()–>m2.pre_process()–>m3.pre_process()-->view()–>m3.after_process()–>m2.after_process()–>m1.after_process()
中间件不区分具体哪个视图,对所有视图都生效

  1. 在客户端和服务端交互的过程中,有些准备工作或扫尾工作需要处理,如:
    1. 在 请求开始时,建立数据库连接
    2. 在请求开始时,根据需求进行权限校验
    3. 在请求结束时,指定数据的交互格式
  2. 为了让每个视图函数避免编写重复功能的代码,Flask提供了通用的设施功能,即请求钩子,请求钩子通过装饰器的形式实现,flask支持如下四种请求钩子
    1. before_first_request 处理第一个请求前执行
    2. before_request 在每次请求前执行(若在某装饰器的函数返回了一个响应,视图函数不再被调用)
    3. after_request
      1. 若没有抛出异常,在每次请求后执行
      2. 接收一个参数:视图函数作出的响应
      3. 在此函数中可以对响应值在返回之前做最后一步修改处理
      4. 需要将参数中的响应在此参数中进行响应
    4. teardown_request:
      1. 在每次请求后执行
      2. 接受一个参数:错误信息,如果有相关错误抛出
#请求钩子 启动中间件/中间层
#1.在第一次请求前调用,可以在此方法内部做一些初始化操作、
@app.before_first_request
def before_first_request():
    print('pre_first_request')
#2.在每一次请求前调用,这时已经有请求了,可在这个方法例做校验
#若请求校验不成功,可以直接在此方法中进行响应,直接return之后不执行视图函数

@app.before_request
def before_request():
    print('before_request')
    # if 请求不符合条件
    #     return 要返回的响应
#在执行完视图函数之后不保错会调用,并且会把视图函数所生成的响应传入,可以在此方法中对响应做最后一步统一的处理
@app.after_request
def after_request(response):
    print('after_request')
    response.headers['Content-Type']='application/json'
    return response
#每次请求之后都会调用,会接收一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(response):
    print('teardown_request {}'.format(response))
@app.route('/')
def index1():
    print('view called')
    return 'index'

11.上下文

上下文,即语境、语意,在程序中可以理解为在代码执行到某一时刻时,根据之前代码所做的操作及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情
flask中有两种上下文,请求上下文应用上下文
Flask中上下文对象:相当于一个容器,保存了Flask程序运行过程中的一些信息

  1. 请求上下文(request context)
    1. 思考:在视图函数中,如何取到当前请求的相关数据?如:请求地址,cookie
    2. 在flask中,可以直接在视图函数中使用request这个对象进行获取相关数据,而request就是请求上下文的对象,保存了当前当次请求的相关数据,请求上下文对象有:requestsession
      1. request 封装了HTTP请求的内容,针对的是HTTP请求,举例:user=request.args.get('user) 获取的是get请求参数
      2. session 用来记录请求会话中的信息,针对的是用户信息,举例:session[‘name’]=userid 可以记录用户信息,还可以通过session.get(‘name’)获取用户信息
  2. 应用上下文(application context)
    1. 不是一直都存在的,它只是request context中的一个对app的代理,所谓local proxy,它的作用主要是帮助request获取当前的应用,它是伴request而生,随着request而灭
    2. 应用上下文对象有:current_app, g
      1. current_app(app=Flask(__ name__))
        1. 应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name() 打印当前app的名称,也可用current_app中存储一些变量,如:
        2. 应用启动的脚本是哪个文件,启动时指定了哪些参数
        3. 加载了哪些配置文件,导入了哪些配置
        4. 链了哪个数据库
        5. 有哪些public的工具类,常量
        6. 应用跑在哪个机器上,ip多少,内存多大
        7. 可以在子文件中应用主文件的app对象
      2. g对象
        1. g作为flask程序的全局变量的一个局部变量,充当中间媒介的作用,我们可以通过他在一次请求调用的多个函数间传递一些数据,只与当前请求有关的 , 每次请求都会重设这个变量
#g对象 的使用 相当于一个容器,可以保存数据 适用于当次
from flask import g
def db_query():
    user_id=g.user_id
    user_name=g.user_name
    print('user_id={},user_name={}'.format(user_id,user_name))
@app.route('/')
def get_user():
    g.user_id=4213
    g.user_name='fds'
    ret=db_query()
    return 'g对象应用'

12.上下文综合应用

  1. 需求
    1. 构建认证机制
    2. 对于特定视图可以提供强制要求用户登录的限制
    3. 对于所有视图,无论是否强制要求用户登录,都可以在视图中尝试获取用户认证后的身份信息
#上下文综合应用 1.构建认证机制 2.对于特定视图可以提供强制要求用户登录 3.在所有视图都可以获取用户认证后的身份信息
#特定强制 --装饰器 所有需求--请求钩子
#请求--请求钩子(g对象保存用户身份信息 尝试判断用户的身份 对于未登录的不做处理 放行)--普通视图--强制登录视图--装饰器
#1.请求钩子
from flask import request,abort,current_app,g
@app.before_request
def auther():
    '''利用before_request请求钩子,在进入所有视图前先尝试判断用户的身份: return '''
    #TODO此处使用鉴权机制(如cookie,session,jwt等)鉴别用户身份信息
    #if 已登录用户,用户有身份信息
    g.user_id=234
    #else 未登录用户,用户无身份信息
    # g.user_id=None
#强制登录 装饰器
def login_require(fun):
    def wrapper(*args,**kwargs):
        #判断用户是否登录
        if g.user_id==None:
            abort(401)
        else:
            return fun(*args,**kwargs)
    return wrapper
#视图 普通视图 不要求用户登录
@app.route('/')
def index():
    return 'get user_id is {}'.format(g.user_id)
#视图 强制用户登录
@app.route('/get')
@login_require
def get_user():
    return 'get user_id is {}'.format(g.user_id)

13.独立使用flask上下文方式

  1. app_contextrequest_context
    1. 在flask程序运行的情况下,调试代码时需要使用current_app,g,request这些对象,该如何使用?
    2. app_context
      1. app_context 为我们提供了应用上下文环境,允许我们在外部使用应用上下文current_app,g可以通过with语句进行使用
      2. with app.app_context():
    3. request_context
      1. request_context 提供了请求上下文环境,允许我们在外部使用请求上下文request, session ,可以通过with语句进行使用
#app_context
from flask import Flask 
app=Flask(__name__)
app.redis_cli='redis_cli'
from flask import current_app
with app.app_context():
    print(current_app.redis_cli)

#request_context
from flask import Flask 
app=Flask(__name__)
environ={'wsgi.version':(1,0),'wsgi_input':''}
with app.request_context(environ):
    print(request.path)

14.上下文实现原理

  1. Threadlocal 线程局部变量
  2. 可以理解为将线程id与数据组合为字典保存

15.定制返回JSON格式

  1. 需求 想要接口返回的JSON数据具有如下统一格式:
    1. {‘message’:‘描述’,‘data’:{要返回的具体数据}}
  2. 在接口处理的正常情况下,message返回ok即可,但是若想每个接口正确返回省略message字段
class DemoResource(Resource):
    def get(self):
        return ('user_id':1,'name':'itcase')
# 对于诸如此类的接口,能否在某处统一格式化成上述需求格式
{'messgae':'ok','data':{'user_id':1,'name':'itcast'}}
# 解决:
# Flask-RESTful的Api对象提供了一个representation的装饰器,允许定制返回数据的呈现格式
api=Api(app)
@api.representation('application/json')
def handle_json(data,code,headers):
    #TODO 此处添加自定义处理
    return resp
# Flask-RESTful原始对于json的格式 处理方式如下:
# 代码如下:flask_restful.representations.json




你为天鹅我为蟾,千思百梦饱一餐

你可能感兴趣的:(flask,python)