在前面学习了 Django 框架之后,接着学习 Flask 框架。相对于 Django 来说,Flask 属于轻量级的 Web 框架,Django 被认为是"大而全"的重量级 Web 框架,其自带大量的常用工具和组件;和Django 不同的是 Flask 轻巧、简洁,可通过第三方拓展来实现具体的功能。Flask 的两个主要核心应用是 Werkzeug (Werkzeug 是一个 WSGI 工具包,web 框架的底层库)和模板引擎 Jinja2。
Flask 框架属 Python 第三方库,使用前须进行安装:pip install flask==1.1.1。
1.第1个 Flask 程序
对于一个基本的 Flask 程序,基本运行流程如下:
下面来实现 Flask 框架的第1个应用程序,在 app.py 文件下编写如下代码;
# 引入flask
from flask import Flask
# 创建flask实例
app = Flask(__name__)
app.debug = True
# 设置路由分发
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
运行后可看到效果如下;
在上面编写第1个应用程序的时候,我们将 Debugger 值调为已激活模式,直接在代码中编写 app.debug = True ,除了这种方法,我们还可以将配置内容放在配置文件中,方便管理。
在主项目下创建 config/config.conf 将要配置的内容放入文件中;
DEBUG = True # 一定要大写
在 app.py 文件中使用 from_pyfile()函数来获取配置内容;
from flask import Flask
# 创建flask实例
app = Flask(__name__)
app.debug = True
app.config.from_pyfile('./config/config.conf')
# 设置路由分发
@app.route('/')
def hello_world():
return 'Hello World! %s' % app.config['DEBUG']
if __name__ == '__main__':
# run(host=None, port=None, debug=None, ...)
app.run()
可以发现它的效果是一样的,也可以激活;
2.Flask 视图
(1)路由网址 URL
若要查看所有网址信息内容,可以使用 Flask 对象的 url_map 属性进行查看;
# 引入flask
from flask import Flask, redirect, url_for
from werkzeug.routing import BaseConverter
# 创建flask实例
app = Flask(__name__)
app.config.from_pyfile('./config/config.conf')
# 设置路由分发
@app.route('/')
def hello_world():
return 'Hello World! %s' % app.config['DEBUG']
@app.route('/python/')
def hello_python():
return 'Hello python!'
if __name__ == '__main__':
# 在测试环境下开启服务
print("所有的网址:",app.url_map)
app.run()
执行程序后,显示如下:
补充:当使用装饰器装饰多个视图时,显示的效果是第1个 视图函数的内容值;当同一视图函数使用多个装饰器来装饰时,使用哪一个装饰器对应的路由网址显示出的内容相同。
(2)使用 url_for 反解析网址
# 引入flask
from flask import Flask, redirect, url_for
from werkzeug.routing import BaseConverter
# 创建flask实例
app = Flask(__name__)
# app.debug = True
app.config.from_pyfile('./config/config.conf')
# 设置路由分发
@app.route('/')
def hello_world():
return 'Hello World! %s' % app.config['DEBUG']
@app.route('/redirect/')
def redirect_index():
return redirect(url_for('hello_world'))
if __name__ == '__main__':
# 在测试环境下开启服务
print("所有的网址:",app.url_map)
app.run()
在地址栏输入 http://127.0.0.1:5000/redirect 后,页面会从 redirect_index() 视图函数中直接重定向跳转至 hello_world() 视图函数中。
(3)传递参数
常见的参数类型有这几种形式:int、float、path,下面举几个小案例来说明。
# 引入flask
from flask import Flask, redirect, url_for
from werkzeug.routing import BaseConverter
# 创建flask实例
app = Flask(__name__)
# app.debug = True
app.config.from_pyfile('./config/config.conf')
@app.route('/params/<bookid>')
def get_bookid(bookid):
print(type(bookid))
return bookid
@app.route('/params1/<int:bookid>')
def get_bookid1(bookid):
print(type(bookid))
return f'接收结果为:{bookid}'
@app.route('/params2/<path:pathname>')
def get_path(pathname):
return pathname
if __name__ == '__main__':
# 在测试环境下开启服务
print("所有的网址:",app.url_map)
app.run()
显示如下:
(4)自定义转换器
若传递参数时上述几种参数类型不存在,那么可以使用自定义转换器的形式来完成,下面定义一个视图函数,用于接收11位数的手机号码,且手机号第2位可能为345789,编写如下代码;
# 引入flask
from flask import Flask, redirect, url_for
from werkzeug.routing import BaseConverter
# 创建flask实例
app = Flask(__name__)
# app.debug = True
app.config.from_pyfile('./config/config.conf')
# 自定义参数类型转换器
class MyRegex(BaseConverter):
def __init__(self,url_map,regex):
super().__init__(url_map)
self.regex = regex
# 注册类型自定义转换器
app.url_map.converters['regex'] = MyRegex
@app.route('/user/<regex("1[345789]\d{9}"):phone>')
def get_user_phone(phone):
return f'用户的手机号是:{phone}'
if __name__ == '__main__':
# 在测试环境下开启服务
print("所有的网址:",app.url_map)
app.run()
效果如下(用法与正则有些相似):
3.request 对象
(1)request 属性
request属性有很多,这里就对 form、data 两个属性来进行说明;
① form;
import json
from flask import Flask, request
app = Flask(__name__)
app.debug = True
# 默认时请求为get,可以设置成不同的请求方式
@app.route('/',methods=['GET','POST'])
def index():
# form -- 获取post数据
username = request.form.get('username')
password = request.form.get('password')
return f"username:{username},password:{password}"
if __name__ == '__main__':
app.run()
效果如下:
② data;
import json
from flask import Flask, request
app = Flask(__name__)
app.debug = True
# 默认时请求为get,可以设置成不同的请求方式
@app.route('/',methods=['GET','POST'])
def index():
print(request.data)
data = request.data.decode('utf-8')
return f"{data}"
if __name__ == '__main__':
app.run()
(2)上传文件
若要将已上传的文件存储在内存或是文件系统中的一个临时的位置,可以通过请求对象的 files 属性访问。每个上传的文件都会存储在这个字典里;
import json
from flask import Flask, request
app = Flask(__name__)
app.debug = True
@app.route('/upload',methods=['POST'])
def upload():
file_obj = request.files.get('avatar')
if not file_obj:
return '未上传图片'
else:
file_obj.save('./static/images/1.jpg')
return "image save ok"
if __name__ == '__main__':
app.run()
这里我们创建一个 uploadImg.html 文件去渲染页面;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="avatar">
<input type="submit" value="上传">
</form>
</body>
</html>
访问后,会出现如图所示,当上传完图片后,在目录中的 static/images 下可以看到图片;