让Flask的路由URL支持正则


flask跟web.py差别挺大的,尤其是在路由管理这块。web.py把所有的路由都集中在一起,我比较喜欢这种方式。最近用flask,发现 @app.route('<URL>') 中URL只支持string、int、float、path 4种类型,并不支持正则。

但我觉得flask绝对没有这么低级,肯定有支持的方法,所以来向各路长老求个方子

python flask

琉璃色之月 10 years, 11 months ago

通过运行如下代码:

from flask import Flask
from pprint import pprint

if __name__ == '__main__':
    app = Flask(__name__)
    pprint(app.url_map.converters)

可以获取Flask默认支持的转换器:

{'any': <class 'werkzeug.routing.AnyConverter'>,
 'default': <class 'werkzeug.routing.UnicodeConverter'>,
 'float': <class 'werkzeug.routing.FloatConverter'>,
 'int': <class 'werkzeug.routing.IntegerConverter'>,
 'path': <class 'werkzeug.routing.PathConverter'>,
 'string': <class 'werkzeug.routing.UnicodeConverter'>}

那如何创建一个新的路由解析转化器呢?
在Flask的app.py里有个简单的例子,这个例子是创建了一个list类型的路由转换器:

from werkzeug.routing import BaseConverter           

class ListConverter(BaseConverter):                  
    def to_python(self, value):                      
        return value.split(',')                      
    def to_url(self, values):                        
        return ','.join(BaseConverter.to_url(value)  
                        for value in values)         

app = Flask(__name__)                                
app.url_map.converters['list'] = ListConverter

那么我们可以容易创建一个正则解析器,因为之前的转换器最终也是转换成正则的,只需要将获取的值设置为regex属性就可以使用了:

from flask import Flask
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter):
    def __init__(self, map, *args):
        self.map = map
        self.regex = args[0]

app = Flask(__name__)
app.url_map.converters['regex'] = RegexConverter

@app.route('/view/<regex("[a-zA-Z0-9]+"):uuid>/')
def view(uuid):
    """
    url: /view/1010000000125259/
    result: view uuid:1010000000125259
    """
    return "view uuid: %s" % (uuid)

@app.route('/<regex(".*"):url>')
def not_found(url):
    """
    url: /hello
    result: not found: 'hello'
    """
    return "not found: '%s'" % (url)

if __name__ == '__main__':
    app.run()
懒洋洋的橙 answered 10 years, 11 months ago

Your Answer