Python Flask: Restful URL


本文讲述如何使用 Python Flask Web 框架构建支持 Restful URL 的 Web 应用。

简单来说,Restful URL可以看做是对 URL 参数的替代。

建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

编写代码

编辑server.py:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/user/<username>')
def user(username):
    print(username)
    print(type(username))
    return 'hello ' + username


@app.route('/user/<username>/friends')
def user_friends(username):
    print(username)
    print(type(username))
    return 'hello ' + username


if __name__ == '__main__':
    app.run(port=5000, debug=True)

运行HelloWorld/server.py。使用浏览器访问http://127.0.0.1:5000/user/letian,HelloWorld/server.py将输出:

letian
<class 'str'>

而访问http://127.0.0.1:5000/user/letian/,响应为404 Not Found。

浏览器访问http://127.0.0.1:5000/user/letian/friends,可以看到:

Hello letian. They are your friends.

HelloWorld/server.py输出:

letian
<class 'str'>

转换类型

由上面的示例可以看出,使用 Restful URL 得到的变量默认为str对象。如果我们需要通过分页显示查询结果,那么需要在url中有数字来指定页数。按照上面方法,可以在获取str类型页数变量后,将其转换为int类型。不过,还有更方便的方法,就是用flask内置的转换机制,即在route中指定该如何转换。

新的服务器代码:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/page/<int:num>')
def page(num):
    print(num)
    print(type(num))
    return 'hello world'


if __name__ == '__main__':
    app.run(port=5000, debug=True)

@app.route('/page/<int:num>')会将num变量自动转换成int类型。

运行上面的程序,在浏览器中访问http://127.0.0.1:5000/page/1,HelloWorld/server.py将输出如下内容:

1
<class 'int'>

如果访问的是http://127.0.0.1:5000/page/asd,我们会得到404响应。

在官方资料中,说是有3个默认的转换器:

int     accepts integers
float   like int but for floating point values
path    like the default but also accepts slashes

看起来够用了。

一个有趣的用法

如下编写服务器代码:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/page/<int:num1>-<int:num2>')
def page(num1, num2):
    print(num1)
    print(num2)
    return 'hello world'


if __name__ == '__main__':
    app.run(port=5000, debug=True)

在浏览器中访问http://127.0.0.1:5000/page/11-22HelloWorld/server.py会输出:

11
22

编写转换器

自定义的转换器是一个继承werkzeug.routing.BaseConverter的类,修改to_pythonto_url方法即可。to_python方法用于将url中的变量转换后供被@app.route包装的函数使用,to_url方法用于flask.url_for中的参数转换。

下面是一个示例,将HelloWorld/server.py修改如下:

from flask import Flask, url_for

from werkzeug.routing import BaseConverter


class MyIntConverter(BaseConverter):

    def __init__(self, url_map):
        super(MyIntConverter, self).__init__(url_map)

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return value * 2


app = Flask(__name__)
app.url_map.converters['my_int'] = MyIntConverter


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/page/<my_int:num>')
def page(num):
    print(num)
    print(url_for('page', num=123))   # page 对应的是 page函数 ,num 对应对应`/page/<my_int:num>`中的num,必须是str
    return 'hello world'


if __name__ == '__main__':
    app.run(port=5000, debug=True)

浏览器访问http://127.0.0.1:5000/page/123后,HelloWorld/server.py的输出信息是:

123
/page/123123

本节源码

源码

值得读

理解RESTful架构



(本文完)


Python Flask 框架教程