Flask入门
常见python-web框架:
django:大而全的web框架,自己内置了很多app,第三方适配的模块也多,但由于过于全,在开启小项目时,略显臃肿。
flask:小而精的python-web框架,甚至可以在一个py文件中完成web最基础的功能,而完成更丰富的功能则需要借助第三方模块。
web.py:是一个小巧灵活的Python框架,它简单而且功能强大(国内几乎没有用的)
常见的异步web框架:
fastapi:python的异步web框架,不少公司在用,专门做前后端分离用于写接口
https://fastapi.tiangolo.com/zh/
sanic:python的异步web框架,供支持异步高并发请求的 web 服务
tornado:异步框架,用的比较少了:
这里需要强调所谓同步框架和异步框架,是有本质上的区别的:
同步框架并不代表没有使用异步,而是对于处理请求到返回响应的过程是同步的,一个线程只能处理一个请求,请求在响应前一直占据此线程。同步框架项目也会有异步并发,如django就可以同时处理多个请求(虽然并发量很小)是通过网关服务器实现的。
异步框架则可以灵活的调度线程,当处理请求的过程中出现了IO等阻塞操作,就会将当前线程重新分配用于处理其他请求,可以非常显著的提高cpu的利用率和并发量。
简单来说:
- 同步框架的一个线程只能处理一个请求
- 异步框架的一个线程可以处理多个请求
flask简介
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架。
jinja2是支持模板语法的模块,可以用于在html文档中用特殊的模板语法进行插值渲染,主要用于前后端混合的项目。
Werkzeug WSGI 符合wsgi协议的web服务器,与django使用的wsgiref是不同的web服务器。
Hello World
from flask import Flask
app = Flask(__name__) # 初始化app
@app.route('/') # 注册路由
def index(): # 视图函数
return 'hello world'
if __name__ == '__main__':
app.run() # 启动项目
前后端混合项目演示
这个小项目用了古老的表单标签(使用form标签可以发送post请求的特性)。
html模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
<input type="text" name="num1"> +
<input type="text" name="num2"> = {{summary}}
<input type="submit" value="计算"> {{error}}
</form>
</body>
</html>
py文件(项目后端)
from flask import Flask, request, render_template
app = Flask(__name__)
# 根路径
@app.route('/', methods=['GET', 'POST'])
def index():
# flask不需要传入request对象,使用全局的request
if request.method == 'GET':
return render_template('login.html') # 返回模板
else:
if num1.isdigit() and num2.isdigt():
return render_template('sum.html',summary=int(num1)+int(num2))
else:
return render_template('login.html', error='输入的不是纯数字') # 注意跟django的render区分,要模板渲染的数据,直接key=value传即可
首先浏览器按照路由发送get请求拿到html文件,在页面中,输入两个数字,点击提交,则会向本地址(相同路由)发送post请求,再进入post的分支,携带插值变量渲染html模板返回前端。
flask基础
-
注册路由可以通过装饰器
app.route(路径,methods=[请求方式,'get','post'])
,加装在某个函数上,这个函数就是视图函数了,路径中可以使用转换器动态匹配路由 -
视图函数必须返回响应内容,基础的有:
- render_template 按模板返回
- redirect 重定向到其他路由
- 字符串 与django的HttpResponse类似
- jsonify 返回json格式字符串(内部可以填入列表,字典等)
-
请求的request对象,是全局的,直接导入使用即可,在不同视图函数中不会混乱
-
session 全局的,直接导入使用即可
要使用session前一定要指定秘钥app.secret_key = '越复杂越好'
-
模板渲染使用的jinjia2,比django的模板语法更强大,可以加括号传参调用,还可以使用中括号取值等。
flask配置方式
flask有多种配置方式,在此罗列一下:
-
flask对象
app=Flask()
中,可以app.debug
和app.secret_key
,配置debug和秘钥app.config['配置键'] = 配置值
可以设置其他配置项 -
使用py文件导入(类似于django的settings.py)
app.config.from_pyfile("settings.py")
类似于django项目中的策略,但在flask中还有更好的方案。
-
(常用)导入类配置项
## settings.py class ConfigBase: DEBUG=False 一些配置项。。。 class DevConfig(ConfigBase): DEBUG=True # 开发环境中debug为true mysql=测试库 # 开发时用测试库 class ProdConfig(ConfigBase): mysql=上线库 # 实际上线用不一样的库配置 ## 导入配置 app.config.from_object('settings.DevConfig')
-
其他:
# 通过环境变量配置 app.config.from_envvar("环境变量名称") # 通过json文件配置 app.config.from_json("json文件名称") # 通过字典格式配置 app.config.from_mapping({'DEBUG': True})
字典格式配置在一些大型公司中会用到,因为会建立大的配置中心,多台机器可能都使用这个配置中心的配置,启动时先朝配置中心发送一个请求,它会返回一个字典(验证通过时),方便我们做集群化部署等。
对于项目的配置,我们可以定义为,供给给项目启动后自动加载的不再变化的量。而这些配置可以是flask的内置配置字段,用于支持flask的web服务,也可以是其他模块的配置字段,如redis、mysql的连接地址等。
路由系统
写法及原理
flask配置路由的基础写法是装饰器:
@app.route('/')
def index():
pass
也就是将index这个普通函数替换成了带路由的视图函数。按照有参装饰器的语法糖,index被替换为app.route('/')(index),查看route的源码,即被替换成了decorator(index)这个闭函数。
其内部最核心的就只执行了self.add_url_rule(rule, endpoint, f, **options)
,而self在这个语境中是flask的对象app。
所以flask路由的本质是app对象的add_url_rule完成路由的注册
add_url_rule的参数
rule 匹配的规则(路径,可能含转换器)
view_func 视图函数,即被装饰的函数
defaults = None 视图函数可能会需要一些额外的参数,通过defaults = {'k': 'v'}提供
endpoint = None 路径的别名,名称,用于反向解析URL,反向解析用到一个函数url_for('endpoint名称')
methods = None 允许的请求方式,如:["GET", "POST"]
strict_slashes = None 对URL最后的 / 符号是否严格要求
redirect_to = None 访问这个路由相当于重定向到redirect_to
转换器
路由中可能包含一些视图函数所需的参数,通过转换器对路由的某一部分进行动态匹配并传参给视图。
使用方式:
@app.route('/student/<int:pk>')
@app.route('/media/<path:path>')
转换器的格式为<转换器类型:匹配内容的变量名>
转换器类型有:
转换器 | 说明 |
---|---|
default | UnicodeConverter |
string | UnicodeConverter |
any | AnyConverter |
path | PathConverter |
int | IntegerConverter |
float | FloatConverter |
uuid | UUIDConverter |