day01_flask入门
一、创建项目
-
创建一个虚拟环境
-
安装Flask框架,点击底部Python Packages选项,搜索Flask软件包
-
看到已安装的软件中存在flask和jinja2即可
-
如果上述方式无法打开则使用命令行终端执行下载命令 ○ 建议修改终端配置,修改为cmd模式
pip install flask
2 启动web服务器
- 创建一个demo.py文件,导入对应的Flask依赖包,并启动服务器
python
# 导入Flask类
from flask import Flask
# Flash 接收一个参数__name__,当前模块的文件名
# Flash 在查找静态文件或模板时会默认以文件所在目录去查找
app = Flask(__name__)
# 装饰器将路由映射到视图index方法
@app.route('/')
def index():
return "hello ~"
if __name__ == '__main__':
# Flash 应用程序实例的方法run启动web服务器
app.run()
3 初始化参数
import_name
: 导包的目录 static_path
: 访问静态资源的路径 static_url_path
: 访问静态文件的url前缀 static_folder
: 默认'static' template_folder
: 默认'templates'
实例化Flask对象后,静态文件默认在模块所在目录下的static
目录,模板使用templates
目录(需手动创建)。 示例:在static目录放图片01.jpeg,访问路径:http://127.0.0.1:5000/static/01.jpeg
自定义配置示例:
python
app = Flask(__name__,
static_folder='static', # 静态文件目录名
template_folder='templates' # 模板文件目录名
)
4 配置
Flask无默认配置文件,需自定义两种方式:
-
从配置文件读取 :
app.config.from_pyfile('文件名')
-
创建
config.cfg
(变量名全大写):DEBUG = True
-
在代码中加载:
app.config.from_pyfile('config.cfg')
-
-
从类读取 :
app.config.from_object(类名)
pythonclass Config(object): DEBUG = True app.config.from_object(Config)
注意:
配置变量名需大写
多个配置同名时后加载的覆盖前面的
5 app.run参数
-
host
: 服务器主机地址(默认'127.0.0.1') -
port
: 端口号(默认5000) -
debug
: 是否开启调试(默认False)
示例:
app.run(host='0.0.0.0', port=8088, debug=True) # 监听所有IP
输出示例:
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8088
* Running on http://192.168.31.149:8088
6. 读取templates中的模板文件
from flask import Flask, render_template
@app.route('/home')
def index():
return render_template('home.html') # 需在templates目录创建home.html
二、路由配置
1. 认识路由
路由是根据URL找到对应视图函数的过程。两种构建方式:
-
装饰器 :
@app.route(url规则)
-
方法 :
add_url_rule(rule, endpoint=None, view_func=None, **options)
-
rule
: URL规则字符串 -
endpoint
: 注册规则的端点(默认视图函数名) -
view_func
: 视图函数
-
python
# 装饰器方式
@app.route('/')
def index():
return 'ok'
# 等效方法
app.add_url_rule('/', 'index', index)
2. 查看路由信息
通过app.url_map
查看所有路由:
python
@app.route('/')
def index():
print(app.url_map) # 输出路由信息
return "我是初始页"
@app.route('/home')
def home():
return "我是首页"
输出示例:
Map([
<Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>,
<Rule '/' (HEAD, GET, OPTIONS) -> index>,
<Rule '/home' (HEAD, GET, OPTIONS) -> home>
])
3. 同一路由装饰不同视图
只有第一个视图生效: 同一个路由规则装饰不同函数,只有第一个视图函数会匹配到。虽然都生成了路由表,但是url匹配中第一个规则之后就会调用视图,不再继续往下匹配。
python
@app.route('/index')
def index1(): # 此函数生效
return '我是第一个'
@app.route('/index')
def index2(): # 不会执行
return '我是第二个'
路由表里面存在,但是不会被读取。所以尽量不要重名

4. 一个视图函数多个路由装饰器
同一视图可绑定多个路由:
python
@app.route('/details1')
@app.route('/details2')
def index1():
return '我是详情页' # 两个URL均可访问
5. methods 参数
HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为
methods 参数接收一个字典,元素为字符串形式的请求方式名称。 如果不传methods参数,默认支持GET, HEAD, OPTIONS
OPTIONS 给客户端提供一个敏捷的途径来弄清这个 URL 支持哪些 HTTP 方法。 从 Flask 0.6 开始,实现了自动处理。
HEAD 浏览器告诉服务器:欲获取信息,但是只关心 消息头 。应用应像处理 GET 请求一样来处理它,但是不分发实际内容。在 Flask 中你完全无需 人工 干预,底层的 Werkzeug 库已经替你打点好了。
指定路由支持的HTTP方法(默认GET):
python
# 注意:需要导入requests库
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return '你用post请求了我'
else:
return '这里是get请求'
6. 反向解析
url_for
通过视图函数名解析URL:
python
@app.route("/python")
def req_python():
return 'python'
@app.route("/url_for")
def req_url():
return f'<a href="{url_for("req_python")}">链接</a>'
7. 动态路由
URL变量放在< >
中,支持类型转换器:
-
int
: 整数 -
float
: 浮点数 -
path
: 结尾含斜线的字符串
python
@app.route('/param/<name>')
def get_url_param(name):
return f'参数:{name}'
@app.route('/param_int/<int:id>')
def get_url_param_int(id):
return f'参数:{id}'
8. 自定义正则转换器
Flask路由转换器,没有提供基于正则的,但是我们可以自定义基于正则的路由转换器
步骤:
-
自定义转换器必须继承BaseConverter类,自定义转换器需要重写父类的init方法
-
注册转换器,url_map中保存了所有的路由转换器,是字典类型
python
from werkzeug.routing import BaseConverter
class RegexListConverter(BaseConverter):
def __init__(self, url_map, *items):
super().__init__(url_map)
self.regex = r'\d+(,\d+)*' # 匹配"1,2,3"
def to_python(self, value):
return value.split(',') if value else []
# 注册转换器
app.url_map.converters['re'] = RegexListConverter
# 使用
@app.route('/param_re/<re(r"\d"):num>/<re(r"\d+"):num2>')
def get_param_re(num, num2):
return f'参数1:{num}, 参数2:{num2}'