Flask 框架
Python 中存在众多的 Web 开发框架:Flask、Django、Tornado、Webpy 等,近几年Django 和 Flask 在 Python 领域中可以说是最主流的两个 Web 开发框架。
1. Flask 与 Django
Flask 是用 Python 语言编写轻量级的 Web 框架,较其他同类型框架更为灵活、轻便且容易上手,小型团队在短时间内就可以完成功能丰富的中小型网站或 Web 服务的实现。
Flask定位为一个轻量级的web微框架,所谓微框架指的是保持核心简单,但其具有很强的定制性,用户可以根据自己的需求来添加相应的功能。
Flask框架与模块分离,可自由扩展,Flask 依赖用各种灵活的扩展(比如邮件 Flask Mail,用户认证 Flask Login,数据库 Flask SQLAlchemy)来给Web应用添加额外功能。
Django 同样由Python 语言编写,遵循 MVC 设计模式,不过Django使用了类似于MVC的MTV设计模式 Model、Template、View ,分别代表模型、模版、视图 。
Django 是一个 Web 开发重框架。所谓‘重’指的是Django 除了实现 Web 框架的基本功能,内置了大量的模块
与 Flask 的架构相比,两者的区别很明显:
- Flask 仅包含最核心的框架功能,没有集成数据库访问、模板引擎等功能;
- Django 不仅包含最核心的框架功能,还包含了数据库访问、模板引擎等功能。
其实两者最主要区别在于:Django 功能大而全,Flask 只包含基本的功能。
2. 最小Flask应用
1 | from flask import Flask # 导入Flask模块 |
3. Flask路由
3.1 在 Flask 中分析 URL 参数
服务端收到客户端发送的数据后,封装形成一个请求对象,在 Flask 中,请求对象是一个模块变量 flask.request,request 对象包含了众多的属性。假设 URL 等于 http://localhost/query?name=zhan,则与 URL 参数相关的属性如下:
属性 | request 获取方式 | 说明 |
---|---|---|
url | request.url | http://localhost/query?name=zhan |
base_url | request.base_url | http://localhost/query |
host | request.host | localhost |
host_url | request.host_url | http://localhost/ |
path | request.path | /query |
full_path | request.full_path | /query?name=zhan |
args | request.args[‘name’] | zhan |
3.2 动态路由
一条固定的路径和一个处理函数相绑定,一条路径对应一个处理函数,无法处理复杂的情况。动态路由,路由中的路径是一个包含有参数的模板,可以匹配多条路径。
<>里的接收到的值可作为参数传递给对应的处理函数
1 | # 默认字符串 |
3.3 Flask 的 request 对象
浏览器访问服务端,需要将相应的数据发送给服务端,可能有如下场景:
- 通过 URL 参数进行查询,浏览器需要将查询参数发送给服务端
- 提交表单 form 进行查询,浏览器需要将表单 form 中的字段发送给服务端
- 上传文件,浏览器需要将文件发送给服务端
服务端收到将客户端发送的数据后,封装形成一个请求对象,在 Flask 中,请求对象是一个模块变量 flask.request,它包含了如下常用属性:
属性 | request获取方式 | 说明 |
---|---|---|
method | request.method | 当前的请求方法 |
form | request.form[‘name’] | 表单参数及其值的字典对象 |
args | request.args | 查询字符串的字典对象 |
values | request.values | 包含所有数据的字典对象 |
json | request.json | 如果 mimetype 是 application/json,这个参数将会解析 json 数据,如果不是则返回 None |
headers | request.headers | http 协议头部 |
cookies | request.cookies | cookie 名称和值的字典对象 |
files | request.files | 与上传文件有关的数据 |
4. Flask模板 -> jinja2
WEB开发中把包含变量和运算逻辑的 html 或其他格式的文本叫做模板,执行这些变量替换和逻辑计算工作的过程被称为渲染, Flask 中使用jinja2引擎完成模板渲染。
在Flask中需要建立templates 目录来存放模板,templates/index.html 是模板文件。
视图简单使用
1 | from flask import Flask, render_template |
4.1 分界符
jinja2 模板文件混合 html 语法与 jinja2 语法,使用分界符区分 html 语法与 jinja2 语法。有 4 种常见的分界符:
1 | - {{ 变量 }},将变量放置在 {{ }} 之间;字符串、列表、字典均可在括号中取值 |
1 | ## for语句 |
4.2 测试
jinja2 提供的 tests 可以用来在语句里对变量或表达式进行测试,语法如下:
1 | {% xxx is test %} |
常见的 test 如下:
test 名称 | 功能 |
---|---|
defined | 变量是否已经定义 |
boolean | 变量的类型是否是 boolean |
integer | 变量的类型是否是 integer |
float | 变量的类型是否是 float |
string | 变量是否是 string |
mapping | 变量的类型是否是字典 |
sequence | 变量的类型是否是序列 |
even | 变量是否是偶数 |
odd | 变量是否是奇数 |
lower | 变量是否是小写 |
upper | 变量是否是大写 |
4.3 过滤器
为了方便对变量进行处理,Jinja2 提供了过滤器filter是一个函数,语法如下:
其过滤函数对输入变量进行变换处理后,返回一个值作为 Jinja2 模板的输出。
1 | {{ xxx | filter }} ## filter(xxx) |
自定义过滤器
自定义过滤器的两种方法:
- 使用
app.add_template_filter(filter_function, filter_name)
,将函数 filter_function 注册为名称为 filter_name 的过滤器; - 使用
@app.template_filter(filter_name) 装饰一个函数 filter_function
,将函数 filter_function 注册为名称为 filter_name 的过滤器。
5. Flask视图
视图函数:将 URL 路径和一个函数关联,根据请求的 URL 调用对应函数处理。
视图类:将 URL 路径和一个视图类关联,根据请求的 URL 调用对应的视图类处理。
视图函数很简单,这里基于视图类展开,使用类视图好处是支持把一些共性东西放父类中,其他子类可继承
Flask.views.View 是 Flask 的标准视图类,用户定义的视图类需要继承于 Flask.views.View。使用视图类的步骤如下:
- 用户定义一个视图类,继承于 views.View;
- 在视图类中定义方法 dispatch_request,处理请求、响应客户端;
- 使用 app.add_url_rule (rule, view_func) 将 URL 路径和视图类绑定
1 | from flask import Flask, views |
视图类的本质仍是视图函数,函数 View.as_view () 返回一个视图函数,当访问页面路径 / 时,最终会调用 dispatch_request ()方法。
5.1 视图类继承
BaseView 提供了 dispatch_request 方法的实现,子类继承了这个方法,不需要重新实现 dispatch_request;BaseView 定义了两个接口函数 get_template 和 get_data,子类必须实现这两个方法。
1 | from flask import Flask, render_template, views |
5.2 在视图类中使用装饰器
1 | from functools import wraps |
6. Flask蓝图 -> Blueprint
Flask中蓝图,提供了模块化管理程序路由的功能,使程序结构更加清晰。
Flask 的 Blueprint 具有如下属性:
- 一个项目可以具有多个 Blueprint;
- Blueprint 可以单独具有自己的模板、静态文件的目录;
- 在应用初始化时,注册需要使用的 Blueprint。
1 | # 主程序 app.py |
在app1和app2中,创建蓝图对象
1 | # app1.py和app2.py |
一个完善的项目,应当
- 程序由主程序和多个蓝图构成;
- 每个蓝图对应一个独立的目录,存储与这个蓝图相关的文件;
- 每个蓝图有一个独立的模板文件目录;
- 每个蓝图有一个独立的静态文件目录。
前端引入静态文件
1 | <link rel="stylesheet" href="{{ url_for('app1.static',filename='app1.css')}}"> |