Skip to content

路由

URL与端点(路由)

视图函数的返回值可以自由修改,返回值作为响应的主体,默认会被浏览器作为 HTML 格式解析,所以可以直接返回一个 HTML 格式的内容:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>学生信息管理系统</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>

然后在后端代码里面添加

python
@app.route('/')
def index():
    return render_template('index.html')

保存修改后,只需要在浏览器里刷新页面,你就会看到页面上的内容也会随之变化。

路由路径

可以自由修改传入 app.route 装饰器里的 URL 规则字符串,来修改访问的网站地址,但要注意以斜线 / 作为开头。比如:

python
@app.route('/home')
def home():
    return 'Welcome to home page !'

绑定路由

一个视图函数也可以绑定多个 URL,这通过附加多个装饰器实现,比如:

python
# 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(删除)。

python
# POST /student  data:{'name': '正心全栈编程'}  
@app.route("/student", methods=["POST"])
def create_student():
    new_student = request.get_json()
    print(new_student)
    return {'msg': '新增数据成功'}

前端发送 post 请求

html

<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('/')

所以之前的写法可以简化为

python
# 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> 的请求:

python
# 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 中间,也可以接收多个参数

python
# 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匹配一系列给定值中的一个元素
uuidUUID 字符串

转换器通过特定的规则指定,即<转换器:变量名><int:phone_number> 把 phone_number 的值转换为整数,因此传入字符串内容进行请求后端就会报错:

python
@app.route('/send/<int:phone_number>')
def send(phone_number):
    return '<p>信息已经发送到 %d !</p>' % phone_number

默认的行为不仅仅是转换变量类型,还包括 URL 匹配。

将上面的例子以整型匹配数据,可以如下使用:

python
@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、创建转换器类,保存匹配时的正则表达式

python
from werkzeug.routing import BaseConverter


class MobileConverter(BaseConverter):
    """
    手机号格式
    """
    regex = r'1[3-9]\d{9}'
  • 注意regex名字固定

2、将自定义的转换器告知Flask应用

python
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter

3、在使用转换器的地方定义使用

python
@app.route('/sms_codes/<mobile:mob_num>')
def send_sms_code(mob_num):
    return 'send sms code to {}'.format(mob_num)