Python Flask框架详解

  Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展,都需要用第三方的扩展来实现,比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。

  其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。

Flask常用扩展包:

  • Flask-SQLalchemy:操作数据库;
  • Flask-script:插入脚本;
  • Flask-migrate:管理迁移数据库;
  • Flask-Session:Session存储方式指定;
  • Flask-WTF:表单;
  • Flask-Mail:邮件;
  • Flask-Bable:提供国际化和本地化支持,翻译;
  • Flask-Login:认证用户状态;
  • Flask-OpenID:认证;
  • Flask-RESTful:开发REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和时间;
  • Flask-Admin:简单而可扩展的管理接口的框架
  1. 中文文档(http://docs.jinkan.org/docs/flask/)
  2. 英文文档(http://flask.pocoo.org/docs/0.11/)
  3. 扩展列表:http://flask.pocoo.org/extensions/
#安装
pip install flask==0.10.1      # 后面为版本号

1、新建文件helloworld.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()    # 可以指定运行的主机IP地址,端口,是否开启调试模式
    # app.run(host="0.0.0.0", port=8888, debug = True)

2、相关配置参数

Flask 程序实例在创建的时候,需要默认传入当前 Flask 程序所指定的包(模块)

app = Flask(__name__)

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

3.加载配置文件

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

  • 从配置对象中加载(常用)
    • app.config.form_object()
  • 从配置文件中加载
    • app.config.form_pyfile()
    从环境变量中加载(不常用)
    • app.config.from_envvar()

3.1配置对象加载

# 配置对象,里面定义需要给 APP 添加的一系列配置
class Config(object):
    DEBUG = True


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

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

3.2配置文件加载

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

格式eg: DEBUG = True

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

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

3.4读取配置

  • app.config.get()
  • 在视图函数中使用 current_app.config.get()

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

4 路由定义

4.1指定路由地址

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

4.2 给路由传参

# 路由传递参数
@app.route('/user/')
def user_info(user_id):
    return 'hello %s' % user_id

# 路由传递的参数默认当做 string 处理,也可以指定参数的类型

# 路由传递参数
@app.route('/user/')
def user_info(user_id):
    return 'hello %d' % user_id

4.3指定请求方式

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

  • GET
  • OPTIONS(自带)
  • HEAD(自带)
@app.route('/login', methods=['GET', 'POST'])  # 支持GET和POST,并且支持自带的OPTIONS和HEAD
def login():
    # 直接从请求中取到请求方式并返回
    return request.method

4.4 正则匹配路由

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

具体实现步骤为:

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

(1)导入转换器基类

from werkzeug.routing import BaseConverter

(2)自定义转换器

# 自定义正则转换器
class RegexConverter(BaseConverter):
    def __init__(self, url_map, *args):
        super(RegexConverter, self).__init__(url_map)
        # 将接受的第1个参数当作匹配规则进行保存
        self.regex = args[0]

(3)添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re

app = Flask(__name__)

# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter

(4)使用转换器去实现自定义匹配规则

# 当前此处定义的规则是:3位数字
@app.route('/user/')
def user_info(user_id):
    return "user_id 为 %s" % user_id
# 系统自带转换器
DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}
# 系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数

自定义转换器其他两个函数实现:

继承于自定义转换器之后,还可以实现 to_python 和 to_url 这两个函数去对匹配参数做进一步处理:

  • to_python:
    • 该函数参数中的 value 值代表匹配到的值,可输出进行查看
    • 匹配完成之后,对匹配到的参数作最后一步处理再返回,比如:转成 int 类型的值再返回:
class RegexConverter(BaseConverter):
    def __init__(self, url_map, *args):
        super(RegexConverter, self).__init__(url_map)
        # 将接受的第1个参数当作匹配规则进行保存
        self.regex = args[0]

    def to_python(self, value):
        return int(value)   # 在视图函数中可以查看参数的类型,由之前默认的 str 已变成 int 类型的值
  •   to_url:
    •   在使用 url_for 去获取视图函数所对应的 url 的时候,会调用此方法对 url_for 后面传入的视图函数参数做进一步处理
    •   具体可参见 Flask 的 app.py 中写的示例代码:ListConverter

 5.简单视图

5.1 返回json

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

# 返回JSON
@app.route('/demo')
def demo():
    json_dict = {
        "user_id": 10,
        "user_name": "laowang"
    }
    return jsonify(json_dict)
注:不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,如果是 JSON 需要指定 content-type:application/json

5.2重定向

(1)重定向到百度

# 重定向
@app.route('/demo')
def demo():
    return redirect('http://www.baidu.com')

(2)重定向到自己写的视图函数

  • 直接填写自己 url 路径
  • 使用 url_for 生成指定视图函数所对应的 url
@app.route('/demo1')
def demo1():
    return 'demo1'

# 重定向,采用url_for生成demo1对应的url
@app.route('/demo2')
def demo2():
    return redirect(url_for('demo1'))

(3)重定向到带有参数的视图函数

# 路由传递参数
@app.route('/user/')
def user_info(user_id):
    return 'hello %d' % user_id

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

5.3自定义状态码

自定义不符合 http 协议的状态码

@app.route('/demo')
def demo():
    return '状态码为 666', 666

6、异常捕获

6.1 HTTP主动抛出异常

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

6.2捕获错误

  • errorhandler 装饰器
    • 注册一个错误处理程序,当程序抛出指定错误状态码的时候,就会调用该装饰器所装饰的方法
  • 参数:
    • code_or_exception – HTTP的错误状态码或指定异常

例如统一处理状态码为500的错误给用户友好的提示:

# 处理所有500类型的异常

@app.errorhandler(500)
def internal_server_error(e):
    return '服务器搬家了'


# 处理特定的异常项
@app.errorhandler(ZeroDivisionError)
def zero_division_error(e):
    return '除数不能为0'

 7、勾子函数

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

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

为了让每个视图函数避免编写重复功能的代码,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)

执行结果

在第1次请求时的打印:
before_first_request
before_request
after_request
teardown_request

在第2次请求时的打印:
before_request
after_request
teardown_request

 

你可能感兴趣的:(Python Flask框架详解)