Flask-路由视图

Flask对请求的处理的原理
  • flask处理请求过程
    • 所有Flask程序必须有一个应用程序实例,相当于django的project。
    • 当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。
    • 此时,Web服务器使用WSGI(Web Server Gateway Interface)协议,把来自客户端的所有请求都交给Flask程序实例,程序实例使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。
    • 根据每个URL请求,找到具体的视图函数并进行调用。
  • Flask实现路由分发的方式
    • 在Flask程序中,路由的实现一般是通过程序实例的装饰器实现。
  • Flask视图函数返回的内容
    • 字符串内容:将视图函数的返回值作为响应的内容,返回给客户端(浏览器)
    • HTML模版内容:获取到数据后,把数据传入HTML模板文件中,模板引擎负责渲染HTTP响应数据,然后返回响应数据给客户端(浏览器)
Flask应用程序(示例)
  • 实现流程
    • 1.创建一个项目文件夹
    • 2.创建hello.py的文件
    • 3.导入flask类
    • 4.创建Flask实例,Flask类接收参数name,它会指向程序所在的模块
    • 5.通过装饰器的方式,将路由映射到视图函数index
    • 6.启动web服务器,Flask应用程序实例的run方法启动WEB服务器,默认5000端口
  • 代码
flask应用实例的使用和基本配置
  • flask实例初始化
    • from flask  import Flask
    • app = Flask(import_name, static_url_path, static_folder, template_folder)
      • import_name: 模块名,一般写__name__
      • static_url_path: 静态文件访问前缀
      • static_folder: 默认‘static’
      • template_folder: 默认‘templates’
  • 配置参数
    • 第一种方法:通过类来配置
      • 先定义配置相关类
        • class Config(object):
          • DEBUG = True
      • 在通过类来配置flask实例
        • app.config.from_object(Config)
    • 第二种方法:通过文件的方式来配置
      • 创建配置文件,并编辑相关配置
        • DEBUG = True
      • 通过文件来配置flask实例
        • app.config.from_pyfile(“yourconfig.cfg”)
    • 第三种方法: 单条配置
      • app.config['DEBUG'] = True
    • 第四种方法: 在启动应用实例的时候直接添加配置
      • app.run(debug = True)
  • 运行flask引用程序
    • 运行方法
      • app.run()
    • 指定参数运行
      • app.run(host="0.0.0.0", port=5000, debug = True)
        • 可以通过传入参数实现指定端口,设置主机,添加配置的效果
        • host为0.0.0.0的时候,本地和局域网内都可以访问
  • 读取配置参数
    • app.config.get()              读取配置信息
    • current_app.config.get()                 在视图中读取配置信息
  • lask应用实例的其他属性\方法
    • app.url_map     获取当前app所有的路由和视图函数的映射,默认包含了静态文件的映射关系
    • app.url_map.converts     返回所有路由转换器
路由介绍和配置
  • Flask装饰器路由的实现:
    • Flask实现路由的核心:Werkzeug-实现路由、调试和Web服务器网关接口。
    • Werkzeug是一个遵循WSGI协议的python函数库。其内部实现了很多Web框架底层的东西,比如request和response对象;与WSGI规范的兼容;支持Unicode;支持基本的会话管理和签名Cookie;集成URL请求路由等。
    • Werkzeug库的routing模块负责实现URL解析。不同的URL对应不同的视图函数,routing模块会对请求信息的URL进行解析,匹配到URL对应的视图函数,以此生成一个响应信息。
    • routing模块内部有: 
      • Rule类(用来构造不同的路由URL对象),存储路由和视图的映射,
      • Map类(存储所有的URL规则),将多个Rule存入map中,
      • BaseConverter的子类(存储的是参数匹配规则),存储所有的url匹配规则
      • MapAdapter类(负责具体URL匹配的工作),拿到url与Rule进行匹配
  • 路由匹配视图函数的规则
    • 路由在匹配过程中,至上而下依次匹配;
    • 当匹配到视图函数的时候便会将请求信息传递给对应视图函数,不会再向下匹配;
    • 所以当同一个路由匹配多个视图函数的时候,只会去执行第一个视图函数的业务代码;
  • 限定请求方式
    • 配置方法
      • 使用 methods 参数指定可接受的请求方式,可以是多种,默认是GET
      • Flask会默认就含有DEAD、OPTION请求方式
    • 代码示例
  • 指定路由参数
    • 配置方法
      • 将参数部分用尖括号<>括起来,括号中的部分代表是url中的参数部分,默认是字符串类型
      • 指定的参数会传递给视图函数
    • 代码示例
  • 路由转换器
    • 路由转换器的作用
      • 可以限定路由参数的内容
      • 可以通过转化器方法对匹配到的路由参数做相应的处理
    • 使用路由转换器
      • 通过在指定参数的时候调用路由转换器,对参数做限制和处理等
      • #  re:路由转换器名称;括号中的内容是创建转换器实例传递的参数,参数可以传递多个,用" , "隔开
      • @app.route(/user/<re("[0-9]{4}"):user_id>)       
      • def index(user_id):
      • .......
    • Flask自带的路由转换器
      • 查看自带路由转换器方法
        • app.url_map.converts
      • 自带的路由转换器
        • default         UnicodeConverter
          • 可以匹配Unicode类型的数据
        • string         UnicodeConverter
          • 可以匹配Unicode类型的字符串
        • any             AnyConverter
          • 可以匹配固定的几个设定的参数
        • path            PathConverter
          • 可以匹配带"/"路径符号的参数
        • int              IntegerConverter
          • 可以匹配整数类型的字符串
        • float           FloatConverter
          • 可以匹配浮点类型的字符串
        • uuid             UUIDConverter
          • 可以匹配一个32位的唯一通用识别码(uuid风格的)字符串
          • 输出一个唯一的uuid类型的数据的方法
            • import  uuid
            • 1.uuid.uuid1()
            • 2.uuid.uuid4()
          • uuid.uuid1()
    • 自定义路由转换器(正则路由)
      • 导入转换器的父类
        • from werkzeug.routing import BaseConverter
      • 定义正则路由转换器
        • 第一种方法
          • 该方法只能用父类的regex属性定义一种匹配规则,适用性不强
        • 第二种方法
          • 该方法可以实现通过传递进来的匹配规则来进行匹配
      • 将自定义路由转换器添加到默认的转换器列表中,并指定转换器的名称
        • app.url_map.converters['re'] = RegexConverter
    • 路由转换器的其他方法(在自定义路由转换器中使用)
      • to_python( )   方法
        • 功能
          • 在参数匹配完成之后再传入到视图函数之前调用,并将函数处理后的参数内容传入视图函数
        • 代码示例:
          • def to_python(self, value):
            • v = int(value)      将参数转化为整数
            • return v           将参数传递给视图函数
      • to_url():
        • 功能
          • 此方法会在进行路由跳转时在匹配跳转的路由函数之前调用,可使用此方法对url_for传入的内容进行处理
        • 代码示例
          • def to_url(self, value):
            • v  = int(value)
            • return  '%d' % v
视图函数的配置
  • 上下文
    • Flask上下文的概念
      • 相当于一个容器,保存了Flask程序运行过程中的一些信息。
      • Flask中有两种上下文,请求上下文和应用上下文。
    • 应用上下文
      • 概念
        • 它的字面意思是应用上下文,但它不是一直存在的,它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
        • 只有在程序完全运行起来之后才能调用
      • 应用上下文包含
        • current_app
          • 应用程序上下文,用于存储应用程序中的变量,可以通过current_app.变量获取,例如:
            • 应用的启动脚 本是哪个文件,启动时指定了哪些参数
            • 加载了哪些配置文件,导入了哪些配置
            • 连了哪个数据库
            • 有哪些public的工具类、常量
            • 应用跑再哪个机器上,IP多少,内存多大
        • g   变量
          • g作为flask程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据
          • g保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread_id区别
      • current_app
        • 使用方法
          • current_app.name           获取应用名
          • current_app.test_value='value'             给应用实例添加变量
      • g  变量
        • 使用方法
          • g.name        获取g的name属性
          • g.name='abc'       添加g全局变量name
    • 请求上下文
      • 概念
        • Flask从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象是一个很好的例子,它封装了客户端发送的HTTP请求。
        • 要想让视图函数能够访问请求对象,一个 显而易见的方式是将其作为参数传入视图函数,不过这会导致程序中的每个视图函数都增加一个参数,除了访问请求对象,如果视图函数在处理请求时还要访问其他对象,情况会变得更糟。为了避免大量可有可无的参数把视图函数弄得一团糟,Flask使用上下文临时把某些对象变为全局可访问。
        • 只有在程序完全运行起来之后才能调用
      • 请求上下文包含
        • request
          • 封装了HTTP请求的内容,针对的是http请求
        • session
          • 用来记录请求会话中的信息,针对的是用户信息
      • request
        • 使用方法
          • 导入方式
            • from  flask  import request
          • 使用方法
            • request.属性名    获取request上下文中的请求相关信息
        • request对象的属性
          • data             记录请求(请求发送的数据为raw_data)的数据, 数据类型为str     
          • form            记录请求(请求发送的数据为form_data)中的表单数据, 数据类型MultiDict
          • args             记录请求中的查询参数,? 后面的查询字符串, 数据类型MultiDict
          • cookies       记录请求中的cookie信息, 数据类型Dict
          • headers      记录请求中的报文头, 数据类型EnvironHeaders
          • method      记录请求使用的HTTP方法, 数据为GET/POST等
          • url                记录请求的URL地址, 数据类型string
          • files             记录请求上传的文件,为form表单中提交的文件对象组成的字典, 数据类型Dict
          • json          获取前端传递过来的json字符串,并转换成dict类型
      • session
        • 使用方法
          • 导入方式
            • from  flask  import session
          • 使用方法
            • 使用方法参考session状态保持
    • 请求上下文\应用上下文之间的区别
      • 请求上下文:保存了客户端和服务器交互的数据
      • 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等
  • 视图函数返回内容
    • 重定向redirect示例
      • 重定向方法
        • 跳转至其他url
          • from flask import redirect
          • return  redirect('url')     在视图函数中通过redirect函数返回
        • 跳转至其他路由
          • 方法一:
            • 这种方法不适用,因为当路由变化后,将不能成功的匹配到视图函数
          • 方法二:
            • from  flask  import  url_for
            • _external=True    参数表示已绝对路径的形式跳转,默认为相对路径的形式跳转
            • 这种方法可以直接跳转到另一个视图函数去处理,尽管路由映射改变也不影响
    • 返回JSON
      • 返回json数据的方法
        • from flask import jsonify
        • return jsonify(<dict>)       在视图函数中通过jsonify函数返回   
    • 返回模板
      • 返回模板的方法
        • from flask import Flask, render_template
        • return render_template(template_name, **content)
      • 备注:**content参数可以是任意个命名参数
        • 示例:
          • return render_template(remplate_name, key1=value1, key2=value2)
          • 参数中的key1,key2便是模板中模板变量调用参数使用的名字
    • 返回一个respones对象
      • 返回的方法
        • from flask import make_response
        • response = make_response(params)          params:普通python类型数据(需要转换成response对象)
        • return response
    • 回状态码
      • 返回的方法
        • return response, status_code      在返回的响应后面接一个数字,代表响应的状态码
    • 返回一个静态文件
      • 返回静态文件的方法
  • 状态保持
    • 为什么状态保持
      • 因为http是一种无状态协议,不会保持某一次请求所产生的信息,如果想实现状态保持,在开发中解决方式有:
    • 状态保持实现两种方法
      • cookie:数据存储在客户端,节省服务器空间,但是不安全
      • session:会话,数据存储在服务器端
    • 设置与获取cookie的方法
      • 设置cookie的方法
        • response.set_cookie('key', 'value', max_age=second)
          • max_age: cookie最大生存时间,默认是关闭浏览器失效
      • 获取cookie的方法
        • request.cookies.get('key')
      • 删除cookie
        • response.delete_cookie('key')
    • 设置与获取session的方法(默认是将session存储在cookie中的)
      • 设置session的方法
        • 配置SCRET_KEY,导入session方法
          • app.config['SCRET_KEY'] = 'fadfas'    设置为任意不规则字符串
          • from flask import  session
        • 设置session的方法
          • 不带过期时间的设置方法
            • session['key'] = value
          • 带过期时间的设置方法
            • app.permanent_session_lifetime = 数字     单位为秒
      • 获取session的方法
        • session.get('key')
      • 删除session的方法
        • session.pop('key')
    • 通过使用redis,将session存储在redis中
异常的捕获
  • 抛出异常(状态码异常)
    • 抛出异常的方法
      • 通过调用abort()方法,抛出一个给定状态代码的 HTTPException
    • 代码示例
      • from flask import abort
      • abort(500)    # 抛出一个状态码为500的HTTPException异常
  • 捕获异常
    • 捕获异常的方法
      • 注册一个错误处理程序,当程序抛出指定错误状态码或者指定的异常的时候,调用该装饰器所装饰的方法
      • 装饰器接收的参数可以是:1.错误状态码;2.程序抛出的异常对象
      • 捕获到的异常对象对传递给处理程序,程序需要用一个形参来接收
      • 可以将异常对象return回去,会将异常信息字符串返回给客户端
    • 代码示例
      • @app.errorhandler(500)         注册异常处理程序,传入错误状态码\ 指定错误异常类
      • def internal_server_error(e):    定义一个异常处理程序
        • return '服务器搬家了'
请求钩子
  • 请求钩子作用
    • 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理
    • 通过装饰器装饰处理函数的方式,在每次请求的过程中插入对应的处理程序
    • 比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
  • 四种请求钩子的实现
    • before_first_request:在处理第一个请求前运行。 
      • 使用场景:可以在第一次请求到达的时候,开启数据库,一些初始化操作等
    • before_request:在每次请求前运行。
      • 注意:
        • 可以在处理函数中,直接return一个response对象,那样便不会执行view函数,会直接去调用after_request
      • 使用场景:判断访问我们服务器的客户端的身份,如果身份验证通过再将请求传递给路由
    • after_request:如果没有未处理的异常,在每次请求后运行。
      • 注意:
        • 会传递给处理函数一个response对象,处理函数需要接收此参数
        • 一定要return一个response对象,不然客户端接收不到服务器端的响应
      • 使用场景: 比如将批量视图函数返回的响应,加上统一的请求头,设置cookie等;
    • teardown_request:在每次请求后运行,即使有未处理的异常抛出。
      • 备注:
        • 会传递给处理函数一个异常对象参数,处理函数需要接收此参数
        • 如果要针对异常返回给客户端响应,可以return一个异常信息的response
      • 使用场景:当捕获到未处理的异常后,可以根据异常的信息返回给客户端错误的提示
生成铭文进行加密和解密
  • 导入模块
    • from werkzeug.security  import  generate_password_hash, check_password_hash
  • 对密码进行铭文加密
    • password_hash = generate_pass_hash(加密前的密码)
  • 对加密后的密码与未加密字符串匹配(匹配返回True,失败返回False)
    • password = check_password_hash(加密后的字符串,待校验的密码)

刘小恺(Kyle) wechat
如有疑问可联系博主