一、Flask介绍
1、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.0.2
2、Flask与Django框架对比
2.1 flask与django哪个框架好?
- 1.可能没有最好的工具,只有更合适的工具。
- 2.轻重对比
- Flask:轻量级的框架,只提供框架的核心功能
- Django:重量级的框架,提供了丰富的工具、组件
- 3.选择上
- Flask:自由、灵活、高度定制
- Django: 快速实现业务 、不考虑技术选型,越简单直接越好
2.2 Flask与Django对比
django提供了:
- django-admin快速创建项目工程目录
- manage.py 管理项目工程
- orm模型(数据库抽象层)
- admin后台管理站点
- 缓存机制
- 文件存储系统
- 用户认证系统
而这些,flask都没有,都需要扩展包来提供
3、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:简单而可扩展的管理接口的框架
4、Flask官方文档
二、工程搭建
1、环境安装
- 创建虚拟环境
mkvirtualenv flask - p python3
workon # 进入虚拟环境、查看所有虚拟环境
deactivate # 退出虚拟环境
- 安装Flask
使用的是1.0.2版本
pip install flask
2、Flask的第一个程序
创建helloworld.py文件
# 导入Flask类
from flask import Flask
# Flask类接收一个参数__name__
app = Flask(__name__)
# 装饰器的作用是将路由映射到视图函数index
@app.route("/")
def index():
return "Hello World"
# flask应用程序实例的run方法启动服务器
if __name__ == "__main__":
app.run()
启动运行
python helloworld.py
3、参数说明
3.1 Flask对象初始化参数
- import_name
- flask程序所在的包(模块),传
__name__
就可以 - 可以决定flask在访问静态文件时查找的路径
- flask程序所在的包(模块),传
- static_url_path
- 静态文件访问路径,可以不传,默认为
/ + static_folder
- 静态文件访问路径,可以不传,默认为
- static_folder
- 静态文件存储的文件夹,可以不传,默认为
static
- 静态文件存储的文件夹,可以不传,默认为
- template_folder
- 模板文件存储的文件夹,可以不传,默认为
templates
- 模板文件存储的文件夹,可以不传,默认为
修改参数示例:
app = Flask(__name__, static_url_path="/s", static_folder="folder")
3.2 应用程序配置参数
- 应用程序配置参数设置的是一个web应用工程的相关信息,比如:数据库的连接信息,日志的配置信息等。
- 作用:集中管理项目的所有配置信息。
- 使用方式:
- Django将所有配置信息都放到了settings.py文件中,而Flask将配置信息保存到了
app.config
属性中,该属性可以按照字典类型进行操作。
- Django将所有配置信息都放到了settings.py文件中,而Flask将配置信息保存到了
- 读取:
app.config.get("name")
app.config["name"]
- 设置参数的三种主要方式:
- 从配置对象中加载
app.config.from_object(配置对象)
- 从配置文件中加载
app.config.from_pyfile(配置文件)
- 从环境变量中加载
app.config.from_envvar(环境变量名)
- 从配置对象中加载
- 从配置对象中加载
代码示例:
from flask import Flask
class DefaultConfig(object):
"""默认配置"""
SECRET_KEY = "HNhidiwi3442ojnko"
app = Flask(__name__)
app.config.from_object(DefaultConfig)
@app.route("/")
def index():
print(app.config["SECRET_KEY"])
return app.config["SECRET_KEY"]
if __name__ == '__main__':
app.run()
- 从配置文件中加载
示例代码:
新建一个配置文件setting.py
SECRET_KEY = "123fefeifidwhhdho;"
from flask import Flask
app = Flask(__name__)
app.config.from_pyfile("settings.py")
@app.route("/")
def index():
print(app.config["SECRET_KEY"])
return app.config["SECRET_KEY"]
if __name__ == '__main__':
app.run()
- 从环境变量中加载
在linux系统中设置和读取环境变量的方式如下:
export 变量名=变量值 # 设置
echo $变量名 # 读取
flask使用环境变量加载配置的本质是通过环境变量值找到配置文件,再读取配置文件的信息。
环境变量的值为配置文件的绝对路径
代码示例:
在终端中执行如下命令,定义环境变量
export PROJECT_SETTING = "~/setting.py"
from flask import Flask
app = Flask(__name__)
app.config.from_envvar("PROJECT_SETTING", silent=True)
@app.route("/")
def index():
print(app.config["SECRET_KEY"])
return app.config["SECRET_KEY"]
if __name__ == '__main__':
app.run()
关于silent的说明:
表示系统环境变量中没有设置相应值时是否抛出异常
- False 表示不安静的处理,没有值时报错通知,默认为False
- True 表示安静的处理,即使没有值也让False正常的运行下去
拓展:pycharm设置环境变量的方式
总结:三种设置参数方式优缺点
优点 | 缺点 | |
---|---|---|
配置对象中加载 | 可以继承、复用 | 敏感数据暴露 |
配置文件中加载 | 独立文件,保护敏感数据 | 不能继承,文件路径固定,不灵活 |
环境变量中加载 | 独立文件,保护敏感数据;文件路径不固定,灵活 | 不方便操作,要设置环境变量 |
- 项目中的常用方式
使用工厂模式创建Flask app,并结合使用配置对象与环境变量加载配置- 使用配置对象加载默认配置
- 使用环境变量加载不想出现在代码中的敏感配置信息
from flask import Flask
def create_flask_app(config):
"""
创建flask应用
:return:
"""
app = Flask(__name__)
app.config.from_object(config)
# 从环境变量指向的配置文件中读取的配置信息会覆盖掉从配置对象中加载的同名参数
app.config.from_envvar("PROJECT_SETTING", silent=True)
return app
class DefaultConfig(object):
"""默认配置"""
SECRET_KEY = "123QWWDEFGG,"
class DevelopmentConfig(DefaultConfig):
DEBUG = True
app = create_flask_app(DevelopmentConfig)
@app.route("/")
def index():
print(app.config.get("SECRET_KEY"))
return "hello world"
if __name__ == '__main__':
app.run()
3.3 app.run()运行参数
可以指定运行的主机ip地址,端口,是否开启调试模式
app.run(host='0.0.0.0', post='5000', debug=True)
关于DEBUG调试模式:
- 程序代码修改后可以自动重启服务器
- 在服务器出现相关错误的时候可以直接将错误信息返回到前端进行展示
4、开发服务器运行方式
在1.0版本之后,Flask调整了开发服务器的启动方式,由代码编写app.run()
语句调整为命令flask run
启动。
4.1 终端启动
Linux
export FLASK_APP=文件名
flask run
windows
set FLASK_APP=文件名
flask run
说明:
- 环境变量FLASK_APP指明flask的启动实例
flask run -h 0.0.0.0 -p 8000
绑定地址端口flask run --help
获取帮助- 生产模式与开发模式的控制:通过
FLASK_ENV
环境变量指明export FLASK_ENV=production
运行在生产模式,默认此方式export FLASK_ENV=development
运行在开发模式
4.2 Pycharm启动
旧版pycharm设置
三、路由与蓝图
1、路由
1.1 查询路由信息
- 命令行方式
flask routes
- 在程序中获取
在应用中的url_map属性中保存着整个Flask应用的路由映射信息,可以通过读取这个属性获取路由信息
print(app.url_map)
遍历路由信息
for rule in app.url_map.iter_rules():
print("name={} path={}".format(rule.endpoint, rule.rule))
需求:通过访问 / 地址,以json的方式返回应用内的所有路由信息
from flask import Flask
import json
app = Flask(__name__)
@app.route("/")
def index():
"""
返回所有视图url
:return:
"""
rules_iterator = app.url_map.iter_rules()
return json.dumps(
{
rule.endpoint: rule.rule for rule in rules_iterator
}
)
if __name__ == '__main__':
app.run()
1.2 指定请求方式
在Flask中,定义路由其默认的请求方式为:
- GET
- OPPTIONS(自带)
- HEAD(自带)
利用methods
参数指定一个接口的请求方式
@app.route("/users", methods=["POST"])
def index()
return "hello world"
2、蓝图
在Flask中,使用蓝图Blueprint来分模块组织管理。
蓝图可以理解为是一个存储一组视图方法的容器对象,具有如下特点:
- 一个应用可以具有多个Blueprint
- 可以将一个Blueprint注册到任何一个未使用的url下,比如"/user"、"/goods"
- Blueprint可以单独具有自己的模板、静态文件或者其他的通用操作方法,它并不是必须要实现应用的视图函数的
- 在一个应用初始化时,就应该要注册需要使用的Blueprint
但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。
四、请求与响应
1、处理请求
1.1 URL路径参数
Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器语法。
- 例如:有一个请求访问的接口地址为
/users/123
,其中123实际上为具体的请求参数,表明请求123号用户的信息。此时如何从url中提取出123的数据?
from flask import Flask
app = Flask(__name__)
@app.route("/user/<user_id>")
def user_info(user_id):
print(type(user_id))
return "hello user {}".format(user_id)
if __name__ == '__main__':
app.run()
此处的<>即是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配、并以字符串为数据类型类型、 user_id为参数名传入视图。
1.1.1 Flask提供的其他类型的转换器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
from flask import Flask
app = Flask(__name__)
@app.route("/user/<int:user_id>")
def user_info(user_id):
print(type(user_id))
return "hello user {}".format(user_id)
if __name__ == '__main__':
app.run()
1.1.2 自定义转换器
Flask内置的转换器无法满足需求,此时需要自定义转换器。
自定义转换器:
- 创建转换器类,保存匹配时的正则表达式(注意regex名字固定)
- 将自定义的转换器告知Flask应用,并指定转换器使用时名字
- 在使用转换器的地方定义使用
示例:匹配提取/sms_codes/18512345678
中的手机号数据
from flask import Flask
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 1 - 创建转换器类,保存匹配时的正则表达式(注意regex名字固定)
class MobileConverter(BaseConverter):
"""
定义匹配时的正则表达式
"""
regex = r"1[3-9]\d{9}"
# 2 - 将自定义的转换器告知Flask应用,并指定转换器使用时名字为: mobile
app.url_map.converters["mobile"] = MobileConverter
# 3 - 在使用转换器的地方定义使用
@app.route("/sms/<mobile:mob_num>")
def send_sms(mob_num):
return "send sms code to {}".format(mob_num)
if __name__ == '__main__':
app.run()
1.2 其他参数
如果想要获取其他地方传递的参数,可以通过Flask提供的request对象来读取。
属性 | 说明 |
---|---|
data | 记录请求的数据,并转换为字符串 |
form | 记录请求中的表单数据 |
args | 记录请求中的查询参数 |
cookies | 记录请求中的cookie信息 |
headers | 记录请求中的报文头 |
method | 记录请求使用的HTTP方法 |
url | 记录请求的URL地址 |
files | 记录请求上传的文件 |
- 示例一:获取请求
/articles?channel_id=1
中channel_id的参数
from flask import Flask, request
app = Flask(__name__)
@app