路由
URL与端点(路由)
视图函数的返回值可以自由修改,返回值作为响应的主体,默认会被浏览器作为 HTML 格式解析,所以可以直接返回一个 HTML 格式的内容:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>学生信息管理系统</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
然后在后端代码里面添加
@app.route('/')
def index():
return render_template('index.html')
保存修改后,只需要在浏览器里刷新页面,你就会看到页面上的内容也会随之变化。
路由路径
可以自由修改传入 app.route
装饰器里的 URL 规则字符串,来修改访问的网站地址,但要注意以斜线 /
作为开头。比如:
@app.route('/home')
def home():
return 'Welcome to home page !'
绑定路由
一个视图函数也可以绑定多个 URL,这通过附加多个装饰器实现,比如:
# GET /student
@app.route("/main")
@app.route("/student")
def get_students():
return {'msg': '请求数据成功'}
现在无论是访问
http://localhost:5000/main
http://localhost:5000/student
都可以看到返回值。
请求方法(旧)
路由的请求方法常用的有四种,GET(请求)、POST(提交)、PUT(修改)、DELETE(删除)。
# POST /student data:{'name': '正心全栈编程'}
@app.route("/student", methods=["POST"])
def create_student():
new_student = request.get_json()
print(new_student)
return {'msg': '新增数据成功'}
前端发送 post 请求
<script>
let response = fetch("/student", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "正心全栈编程" }),
});
response
.then(function (res) {
return res.json();
})
.then(function (result) {
console.log(result);
});
</script>
methods 参数接收的是一个列表,可以同时处理多种请求。
请求方法(新)
在 flask 2.x 之后,更新了下面几个装饰器。
旧版写法 | 新版写法 |
---|---|
@app.route("/", methods=["GET"]) | @app.get('/') |
@app.route("/", methods=["POST"]) | @app.post('/') |
@app.route("/", methods=["PUT"]) | @app.put('/') |
@app.route("/", methods=["DELETE"]) | @app.delete('/') |
所以之前的写法可以简化为
# POST /student data:{'name': '正心全栈编程'}
@app.post("/student") # 等价于 @app.route("/student", methods=["POST"])
def create_student():
new_student = request.get_json()
print(new_student)
return {'msg': '新增数据成功'}
接收传参
在前面,我们之所以把传入 app.route
装饰器的参数称为 URL 规则,是因为我们也可以在 URL 里定义变量部分。比如下面这个视图函数会处理所有类似 /user/<name>
的请求:
# GET /student/<string:name>
@app.route("/student/<string:name>", methods=["GET"])
def get_student(name):
print("name: " + name)
return {"msg": "请求数据成功"}
不论你访问
http://localhost:5000/student/正心
http://localhost:5000/student/全栈
都可以得到请求内容
接收参数还可以在 url 中间,也可以接收多个参数
# POST /student/<string:name>/recodes {name:, chinese:}
@app.post("/student/<string:name>/recodes")
def create_recode_in_student(name):
print('请求的地址为:', f'/student/{name}/recodes')
return {"msg": "请求数据成功"}
# GET /student/<string:name>/recodes
@app.get("/store/<string:name>/recodes")
def get_recode_in_students(name):
print('请求的地址为:', f'/student/{name}/recodes')
return {"msg": "请求数据成功"}
URL处理(转化器)
从前面的路由列表中可以看到,除了 /student
,这个程序还包含许多 URL 规则,比如和 send 端点对应的 /send/<phone_number>
。
现在请尝试访问 http://localhost:5000/send/phone_number
,在URL中加入一个数字用于当做路由转化器。URL 中的变量部分默认类型为字符串,但 Flask 提供了一些转换器可以在 URL 规则里使用。
Flask 内置的 URL 变量转换器
转换器 | 说 明 |
---|---|
string | 不包含斜线的字符串(默认值) |
int | 整型 |
float | 浮点数 |
path | 包含斜线的字符串。static 路由的 URL 规则中的 filename 变量就使用了这个转换器 |
any | 匹配一系列给定值中的一个元素 |
uuid | UUID 字符串 |
转换器通过特定的规则指定,即<转换器:变量名>
。<int:phone_number>
把 phone_number 的值转换为整数,因此传入字符串内容进行请求后端就会报错:
@app.route('/send/<int:phone_number>')
def send(phone_number):
return '<p>信息已经发送到 %d !</p>' % phone_number
默认的行为不仅仅是转换变量类型,还包括 URL 匹配。
将上面的例子以整型匹配数据,可以如下使用:
@app.route('/users/<int:user_id>')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
自定义转换器
如果遇到需要匹配提取 /sms_codes/18512345678
中的手机号数据,Flask内置的转换器就无法满足需求,此时需要自定义转换器。
自定义转换器主要做 3 步
1、创建转换器类,保存匹配时的正则表达式
from werkzeug.routing import BaseConverter
class MobileConverter(BaseConverter):
"""
手机号格式
"""
regex = r'1[3-9]\d{9}'
- 注意
regex
名字固定
2、将自定义的转换器告知Flask应用
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter
3、在使用转换器的地方定义使用
@app.route('/sms_codes/<mobile:mob_num>')
def send_sms_code(mob_num):
return 'send sms code to {}'.format(mob_num)