浅入浅出Flask框架:RESTful URL

June 28th 2014  | Tags: flask, python, web

2014-06-28

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

入门


建立Flask项目

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

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

编写代码

编辑HelloWorld/index.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 world'

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

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

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

letian
<type 'unicode'>

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

访问http://127.0.0.1:5000/user/letian/friends,能够得到期望的结果。HelloWorld/index.py输出:

letian
<type 'unicode'>

转换类型


由上面的示例可以看出,使用restful url得到的变量默认为unicode对象。如果我们需要通过分页显示查询结果,那么需要在url中有数字来指定页数。按照上面方法,可以在获取unicode类型页数变量后,将其转换为int类型。不过,还有更方面的方法,就是在route中指定该如何转换。将HelloWorld/index.py修改如下:

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(debug=True)

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

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

1
<type '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

肯定够用。

一个有趣的用法


如下编写HelloWorld/index.py

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(debug=True)

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

11
22

编写转换器


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

下面是一个示例,将HelloWorld/index.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 'hi'

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')
    return 'hello world'

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

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

123
/page/hi

资料


关于restful url,可以参考理解RESTful架构
URL参数,可以参考浅入浅出Flask框架:获取URL参数
关于转换器,可以参考Custom ConvertersDoes Flask support regular expressions in its URL routing?

(完)