Flask:

Flask相对于Django而言是轻量级的Web框架。和Django不同,Flask轻巧、简洁,通过定制第三方扩展来实现具体功能。

可定制性,通过扩展增加其功能,这是Flask最重要的特点。Flask的两个主要核心应用是Werkzeug和模板引擎Jinja。

1.1 了解框架:

Flask作为Web框架,它的作用主要是为了开发Web应用程序。那么我们首先来了解下Web应用程序。Web应用程序 (World Wide Web)诞生最初的目的,是为了利用互联网交流工作文档。

flask 数据可视化 flask 视图_客户端

 

  • 一切从客户端发起请求开始。
  • 所有Flask程序都必须创建一个程序实例。
  • 当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。
  • 此时,Web服务器使用一种名为WEB服务器网关接口的WSGI(Web Server Gateway Interface)协议,把来自客户端的请求都交给Flask程序实例。
  • Flask使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。根据每个URL请求,找到具体的视图函数。
  • 在Flask程序中,路由一般是通过程序实例的装饰器实现。通过调用视图函数,获取到数据后,把数据传入HTML模板文件中,模板引擎负责渲染HTTP响应数据,然后由Flask返回响应数据给浏览器,最后浏览器显示返回的结果。

Flask扩展包:

  • Flask-SQLalchemy:操作数据库;
  • Flask-migrate:管理迁移数据库;
  • Flask-Mail:邮件;
  • Flask-WTF:表单;
  • Flask-script:插入脚本;
  • Flask-Login:认证用户状态;
  • Flask-RESTful:开发REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和时间;
  1. 中文文档(http://docs.jinkan.org/docs/flask/
  2. 英文文档(http://flask.pocoo.org/docs/0.11/

Flask程序运行过程:

所有Flask程序必须有一个程序实例。

Flask调用视图函数后,会将视图函数的返回值作为响应的内容,返回给客户端。一般情况下,响应内容主要是字符串和状态码。

当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。此时,Web服务器使用WSGI(Web Server Gateway Interface)协议,把来自客户端的所有请求都交给Flask程序实例,程序实例使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。根据每个URL请求,找到具体的视图函数。 在Flask程序中,路由的实现一般是通过程序实例的route装饰器实现。route装饰器内部会调用add_url_route()方法实现路由注册。

调用视图函数,获取响应数据后,把数据传入HTML模板文件中,模板引擎负责渲染响应数据,然后由Flask返回响应数据给浏览器,最后浏览器处理返回的结果显示给客户端。

第一个Flask案例

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 # 导入Flask类
 2 from flask import Flask
 3 
 4 #Flask类接收一个参数__name__
 5 app = Flask(__name__)
 6 
 7 # 装饰器的作用是将路由映射到视图函数index
 8 @app.route('/')
 9 def index():
10     return 'Hello World'
11 
12 # Flask应用程序实例的run方法启动WEB服务器
13 if __name__ == '__main__':
14     app.run()

View Code

查看视图函数中的路由:

flask 数据可视化 flask 视图_flask 数据可视化_04

给路由传参示例:

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

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 # @app.route('/user/<id>/')  # 默认方式 为str  同时兼容int和float,
2 # int和float互不兼容
3 @app.route('/user/<float:id>/')
4 def get_args(id):
5     print id
6     return 'hello python %s' % id

View Code

返回状态码示例:

return后面可以自主定义状态码(即使这个状态码不存在)。当客户端的请求已经处理完成,由视图函数决定返回给客户端一个状态码,告知客户端这次请求的处理结果。

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 # 可以指定不符合协议的http的状态码
2 @app.route('/status/')
3 def status():
4     return 'hello python',999

view Code

flask 数据可视化 flask 视图_客户端_09

abort函数:

如果在视图函数执行过程中,出现了异常错误,我们可以使用abort函数立即终止视图函数的执行。通过abort函数,可以向前端返回一个http标准中存在的错误状态码,表示出现的错误信息。

使用abort抛出一个http标准中不存在的自定义的状态码,没有实际意义。如果abort函数被触发,其后面的语句将不会执行。其类似于python中raise。

导入:

from flask import abort

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

@app.route('/ssss/')
def get_abort():
    abort(404)
    return 'hello itcast', 666

abort使用Code

捕获异常:

在Flask中通过装饰器来实现捕获异常,errorhandler()接收的参数为异常状态码。视图函数的参数,返回的是错误信息。

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

@app.errorhandler(404)
def err(e):
    print e
    return 'error info %s' % e

异常Code

重定向redirect示例

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 # 重定向
2 from flask import redirect
3 @app.route('/redirect/')
4 def redir():
5     return redirect('https://www.baidu.com')

View Code

正则URL示例:

正则URL是为了匹配指定的URL,而匹配指定的URL则可以达到限制访问,以及优化访问路径的目的。

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

from werkzeug.routing import BaseConverter  # 导入该类
class Regex(BaseConverter):  # 继承
    def __init__(self, url, *args):
        # 调用父类的初始化方法
        super(Regex, self).__init__(url)  # 调用父类的方法
        self.regex = args[0]  # 获取正则表达式
        print(args)

正则url示例Code

设置cookie

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

# 获取cookie信息,实现状态保持
@app.route('/cookie/')
def cookie():
    resp = make_response('welcome kay cookie')  # 页面返回的内容
    resp.set_cookie('name', 'python')
    return resp

设置Code

获取cookie

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 from flask import request
2 # 获取cookie信息,获取requests对象
3 @app.route('/getcookie/')
4 def get_cookie():
5     resp = request.cookies.get('name')  # 是一个字典调用get方法
6     print request.cookiesm  # 返回一个字典
7     return resp

View Code

请求上下文(request context)

  • request和session都属于请求上下文对象。 request:封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。

session:用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id;可以记录用户信息。还可以通过session.get('name')获取用户信息。

  • 当调用app = Flask(_name_)的时候,创建了程序应用对象app;
  • request 在每次http请求发生时,WSGI server调用Flask.call();然后在Flask内部创建的request对象;
  • app的生命周期大于request和g,一个app存活期间,可能发生多次http请求,所以就会有多个request和g。
  • 最终传入视图函数,通过return、redirect或render_template生成response对象,返回给客户端。

应用上下文(application context)

  • current_app和g都属于应用上下文对象。
  • current_app:表示当前运行程序文件的程序实例。我们可以通过current_app.name打印出当前应用程序实例的名字。 

flask 数据可视化 flask 视图_客户端_22

  • g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。比如:我们可以获取一些临时请求的用户信息。

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

请求钩子

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。

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

before_first_request:在处理第一个请求前运行。

before_request:在每次请求前运行。

after_request:如果没有未处理的异常抛出,在每次请求后运行。

teardown_request:在每次请求后运行,即使有未处理的异常抛出。

Flask装饰器路由的实现:

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模式的对象)、Map类(存储所有的URL规则)、MapAdapter类(负责具体URL匹配的工作);

Flask-Script扩展命令行

通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过python hello.py runserver --host ip地址,告诉服务器在哪个网络接口监听来自客户端的连接。默认情况下,服务器只监听来自服务器所在计算机发起的连接,即localhost连接。

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

flask 数据可视化 flask 视图_flask 数据可视化_02

flask 数据可视化 flask 视图_客户端_03

1 from flask import Flask
 2 from flask_script import Manager
 3 
 4 app = Flask(__name__)
 5 
 6 manager = Manager(app)
 7 
 8 @app.route('/')
 9 def index():
10     return '床前明月光'
11 
12 if __name__ == "__main__":
13     manager.run()

View Code