Flask框架(一)
一、Flask框架介绍
1.Flask介绍
Flask诞生于2010年4月,是Armin ronacher用python语言基于Werkzeug工具箱编写的轻量级Web开发框架。
Flask本身相当于一个内核,几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用到第三方的扩展来实现。比如可以用Flaks扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask默认都没有使用的数据库,但是通过扩展可以选择MySQL或者NoSQL
其WSGI工具箱采用Werkzeug(路由模块),模板引擎则使用Jinja2。这两个也是Flask框架的核心。
2.框架对比
1)框架重量级对比
- 重量级的框架:为了方便业务程序开发,提供了丰富的工具、组件,例如Django
- 轻量级的框架:只提供Web框架的核心功能,自由、灵活、高度定制,例如Flask、Tornado
2)与Django对比
- Django提供了,django-admin快速创建项目工程目录
- manage.py 管理项目工程
- ORM模型(数据库抽象层)
- admin后台管理站点
- 缓存机制、文件存储系统、用户认证系统
而Flask默认什么都没有,一切都需要扩展包来实现。
3.常用扩展包
- 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:简单而可扩展的管理接口的框架
了解更多可以查看Flask官方文档,但是不建议作为学习的工具,建议只是作为参考资料。
以下需要虚拟环境和安装flask
二、Flask最基本程序编写hello world
1)程序编写
# 导入Flask类
from flask import Flask
# 创建Flask实例,接收参数__name__表示当前文件名,默认会自动指定静态文件static
app = Flask(__name__)
# 装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
return 'hello world'
# Flask应用程序实例的run方法启动WEB服务器
if __name__ == '__main__':
app.run()
2)运行方式
-
手动运行
python 文件名
-
pycharm运行
在文件中右击,点击运行即可。
三、Flask参数
1)Flask对象初始化参数
Flask程序实例在创建的时候,需要默认传入当前Flask程序所指定的包或者模块;
- import_name
- Flask程序所在的包(模块),传入 ____name____即可
- 其可以决定Flask在访问静态文件时候查找的路径
- static_url_path
- 静态文件访问路径,可以不传,默认为: / + static_folder
- static_folder
- 静态文件所在的文件夹,可以不传,默认为 static
- template_folder
- 模板文件所在的文件夹,可以不传,默认为templates
2)应用程序配置参数
对于Flask对象初始化参数仅仅设置的是Flask本身的属性,比如:
- Flask从哪里读取静态文件
- Flask从哪里读取模板文件等
应用程序配置参数设置的是一个Web应用工程相关信息,比如:
- 数据库的连接信息
- 日志的配置信息
- 自定义的配置信息
作用就是集中管理项目的所有配置信息
使用方式:
Django将所有的配置信息都放到了setting.py文件中,而Flask则不同。
Flask将配置信息都保存到了app.config属性当中,该属性可以按照字典类型进行操作。
读取:
- app.config.get(user)
- app.config[username]
设置:
主要使用以下三种方式:
-
从配置对象中加载
class DdefaultConfig(object): SECRET_KEY = 'KJDFIJSD' app = Flask(__name__) app.config.from_object(DefaultConfig) @app.route('/') def index(): print(app.config['SECRET_KEY']) app.run()
一般作为默认配置写在程序代码中,可以继承
-
从配置文件中加载
新建一个setting.py文件
SECRET_KEY = 'OSDFSDJFLKKLMDFGsdf'
在Flask程序文件
app = Flask(__name__) app.config.from_pyfile('setting.py') @app.route('/') def index(): print(app.config['SECRET_KEY']) app.run()
一般固定不变的配置可以使用此种方式,不建议使用。
-
从环境变量中加载
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件位置和系统文件位置等。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。
通俗的理解,环境变量就是我们设置在操作系统中,由操作系统代为保存的变量值。
-
在Linu系统中设置和读取环境变量的方式如下:
export 变量名=变量值 # 设置 echo $变量名 # 读取
-
Flask使用环境变量加载配置的本质是通过环境变量值找到配置文件,再读取配置文件信息。
在终端执行如下命令:
export PROJECT_SETTING = '~/setting.py'
Flask程序进行如下编写:
app = Flask(__name__) app.config.from_envvar('PROJECT_SETTING',silent=True) @app.route('/') def index(): print(app.config['SECRET_KEY']) return 'environment'
关于silent的说明:
表示系统环境变量中没有设置相应值的时候是否抛出异常
- False表示不安静的处理,没有值的时候会报错,默认为False
- True表示安静的处理,没有值也会正常运行
工厂模式封装App
def create_flask_app(config):
app = Flask(__name__)
app.config.from_object(config)
app.config.from_pyfile('setting.py')
return app
class DefaultConfig(object):
SECRET_KEY = 'www.csdn.net'
class Demo2Config(DefaultConfig):
DEBUG=True
app = create_flask_app(Demo2Config)
@app.route('/')
def index():
print(app.config['SECRET_KEY'])
return 'OK!'
app.run参数
可以指定运行的主机ip地址、端口和是否开启调试模式
# 默认host为"127.0.0.1",port=5000,debug=false
app.run(host='0.0.0.0',port=5001,debug=True)
关于DEBUG调试模式‘
1.程序代码在修改后可以自动跟踪代码状态,不需要手动重启服务器
2.在服务器出现相关错误的时候可以将错误信息返回到前端页面进行显示
四、开启服务器的启动方式
在1.0版本之后,Flask调整了开发服务器的启动方式,由代码编写app.run()语句调整命令为flask run 启动
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'test'
# 程序中可以不再写app.run()
1.终端启动
export FLASK_APP=文件名
flask run
说明:
-
环境变量FLASK_APP指定falsk的启动实例
-
flask run - h 0.0.0.0 -p 5003 可以绑定地址和端口号
-
flask run --help 可以获取帮助信息
-
生产模式与开发模式的控制
-
通过FLASK_ENV环境变量指明
export FLASK_ENV=production 生产模式,默认 export FLASK_ENV=development 开发模式
-
五、路由
1.查询路由信息
-
命令行方式
flask routes # 结果: Endpoint Methods Rule -------- ------- ----------------------- index GET / static GET /static/ # Endpoint 表示端点,默认是视图函数名 # Methods 表示请求方式 # Rule 表示路由规则
-
在程序中获取
在应用的url_map属性中保存着整个Flask应用的路由映射信息,可以通过读取这个属性获取路由信息
print(app.url_map)
如果想在程序中遍历路由信息,可以采用如下方式
for rule in app.url_map.iter_rules(): print('name={} path={}'.format(rule.endpoint,rule,rule))
2.指定请求方式
在Flask中,定义路由的默认请求方式为:
- GET
- OPTIONS(自带)
- HEAD(自带)
利用methods参数可以自己指定一个接口的请求方式
@app.route('/a',methods=['POST','PUT','GET'])
def index():
return '阿斯顿'
# GET方式为默认使用方式,OPTIONS和HEAD请求方式由Flask框架默认处理
六、蓝图
在flask中,使用蓝图blueprint来分模块组织管理。
蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:
- 一个应用可以具有多个blueprint
- 可以将一个blueprint注册到任何一个未使用的URL下
- buleprint可以单独具有自己的模板、静态我呢见或者其他通用的操作方法,它并不是不许要实现应用的视图和函数的
- 在一个应用初始化的时候,就应该注册需要使用的blueprint
使用方式:
使用蓝图可以分为三个步骤
1.创建一个蓝图对象
wtt_bp = Blueprint('wtt',__name__)
2.在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模板过滤器
@wtt_bp.route('/')
def index():
return 'wtt_profile'
3.在应用对象上注册这个蓝图对象
app.register_blueprint(wtt_bp)
可以将创建蓝图对象和定义视图放到一个文件中,但是不建议这样做,因为这样也就失去了蓝图的意义。
目录(包)蓝图
对于一个打算包含多个文件的蓝图,通常将创建蓝图对象放到Python包的____init____.py文件中
扩展用法
1.指定蓝图的url前缀
在应用注册蓝图或者创建对象的时候都可以使用url_prefix参数指定前缀
app.register_blueprint(user_bp,url_prefix='/user')
wtt_bp = Blueprint('wtt',__name__,url_prefix='/order')
2.蓝图内部静态文件
和应用对象不同,蓝图对象创建的时候不会默认注册静态目录的路由。需要我们在创建蓝图对象的时候指定static_folder参数
例如。将static_blueprint目录设置为静态目录
a = Blueprint('a',__name__,static_folder='static_blueprint')
app.register_blueprint(a,url_prefix='/a')
现在就可以使用/a/static_blueprint/来访问static_blueprint目录下的静态文件了。
也可以通过static_url_path参数改变访问url
a = Blueprint('a',__name__,static_url_path='/static',static_folder='static_blueprint')
app.register_blueprint(a,url_prefix='/a')
这回的访问路径变为/a/static/来访问static_blueprint目录下的静态文件。
3.蓝图内部模板目录
蓝图对象默认的模板目录为系统的模板目录,可以在创建蓝图对象的时候使用template_folder关键字参数设置模板目录
wangtaotao = Blueprint('wtt',__name__,template_folder='my_templates')
七、处理请求
1.URL路径参数(动态路由)
例如,有一个请求访问的接口地址为/users/1,表示访问1号用户信息,Flask中可以通过以下方式来接受参数。
Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器的方式:
@app.route('/users/<user_id>')
def users(user_id):
return 'hello user{}'.format(user_id)
此处的<>是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配、并以字符串为数据类型、user_id为参数名传入视图。
Flask也提供其他类型的转换器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
将上面的例子以整型匹配数据,和设置最小值等 可以如下使用,
@app.route('/users/'<int:user_id>)
def user_info(user_id):
return 'hello user{}'.format(user_id)
@app.route('/users/<int(min=10):user_id')
def user_info(user_id):
return 'hello user{}'.format(user_id)
2.自定义转换器
比如我想在路径中匹配一个手机号的参数。
定义方法
自定义转换器主要做3步
1.创建转换器类,保存匹配时候的正则表达式(具体的可以看源码)
from werkzeug.routing import BaseConverter
class MobileConverter(BaseConverter):
# 这个名字不可以变
regex = r'^1[3-9]\d{9}'
2.将自定义的转换器告知flask应用
app = Flask(__name__)
app.url_map.convertes['mobile'] = MobileConverter
3.在使用转换器的地方定义
@app.route('/sms_code/<mobile:mobile_id>')
def send_sms_code(mobile_id):
return '{}'.format(mobile_id)
3.其他参数
如果想要获取其他地方传递的参数,可以通过Flask提供的request上下文对象来获取
不同位置的参数都存放在requests的不通属性中
属性 | 说明 | 类型 |
---|---|---|
data | 记录请求的数据,并转换为字符串 | * |
form | 记录请求中的表单数据 | MultiDict |
args | 记录请求中的查询参数 | MultiDict |
cookies | 记录请求中的cookie信息 | Dict |
headers | 记录请求中的报文头 | EnvironHeaders |
method | 记录请求使用的HTTP方法 | GET/POST |
url | 记录请求的URL地址 | string |
files | 记录请求上传的文件 | * |
例如:想要获取请求/user/?user_id中user_id的值
from flask import request
@app.route('/user')
def get_user_id():
user_id = request.args.get('user_id')
return '提取查询参数'
上传图片
客户端上传图片到服务器,并且保存到服务器中
from flask import request
@app.route('/upload',methods=['POST'])
def upload_file():
f = request.files['image']
#with open('./01.jpg','wb') as file:
# file.write(f.read())
f.save('./01.jpg')
return 'upload image successed!'