在Flask中定义URL路由规则有三种方法:
1、使用flask.Flask.route()装饰器
2、使用flask.Flask.add_url_rule函数
3、直接访问底层的Werkzeug路由系统:flask.Flask.url_map
下面就第1,2两种方法进行讲解:
flask.Flask.route()装饰器的函数原型为:route(rule, **options)
flask.Flask.add_url_rule函数的原型为:add_url_rule(*args, **kwargs)
其实,在底层,route装饰器也是调用add_url_rule函数的。
以下参数是上述两个函数所接受的:
rule:URL的规则,如'/' , '/index' 字符串类型
endpoint:所注册的URL规则的端点。没有特别声明的话,Flask通常将视图函数作为URL规则的端点。
view_func:视图函数,即默认的endpoint,当访问之前定义的rule时,由该函数处理请求。该视图函数也可以通过view_functions字典来指定。该字典的key是函数名称,value是函数本身。
defaults:规则的默认值,字典类型。可以为同一个函数定义多重规则,然而这些规则必须是唯一的。
如:
@app.route('/users/',defaults={'page':1})
@app.route('/users/page/<int:page>')
def show_user(page):
pass
当访问page 1时,URL为/users/ ;当访问page N时,URL为/users/page/N
subdomain:为submain指定规则,目的是防止subdomain matching在使用。如果没有指定的话,采用默认的subdomain。
**options:这些选项传递给底层的Rule对象。如@app.route('/login',methods=['GET','POST'])中的methods选项,默认情况是监听GET方法。
例如:
@app.route('/')
def index():
pass
对于add_url_rule函数来说,等同于:
def index():
pass
app.add_url_rule('/','index',index)
当视图函数没有指定时,可采用上面所说的view_functions字典,app.view_functions['index']=index
变量规则
通过把 URL 的一部分标记为 <variable_name> 就可以在 URL 中添加变量。标记的 部分会作为关键字参数传递给函数。通过使用 <converter:variable_name> ,可以 选择性的加上一个转换器,为变量指定规则。请看下面的例子:
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
现有的转换器有:
int 接受整数
float 接受浮点数
path 和缺省情况相同,但也接受斜杠
唯一的URL/重定向行为
Flask 的 URL 规则都是基于 Werkzeug 的路由模块的。其背后的理念是保证漂亮的 外观和唯一的 URL 。这个理念来自于 Apache 和更早期的服务器。
假设有如下两条规则:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
它们看上去很相近,不同之处在于 URL 定义 中尾部的斜杠。第一个例子中 prjects 的 URL 是中规中举的,尾部有一个斜杠,看起来就如同一个文件夹。访问 一个没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜杠。
但是在第二个例子中, URL 没有尾部斜杠,因此其行为表现与一个文件类似。如果 访问这个 URL 时添加了尾部斜杠就会得到一个 404 错误。
为什么这样做?因为这样可以在省略末尾斜杠时仍能继续相关的 URL 。这种重定向 行为与 Apache 和其他服务器一致。同时, URL 仍保持唯一,帮助搜索引擎不重复 索引同一页面。
底层的Rule对象:
上面提到过底层的Rule对象,Rule对象的原型为:
class werkzeug.routing.Rule(string, defaults=None, subdomain=None, methods=None,build_only=False, endpoint=None, strict_slashes=None, redirect_to=None, alias=False,host=None)
string:URL规则,上面介绍的rule规则、变量规则都适用它
endpoint:可以是函数、字符串、数字等。比较好的选择是字符串,因为endpoint将用于URL生成器中。
defaults:为同一个endpoint设置多个rule。与上面route和add_url_rule中的defaults一样。
如:
url_map=Map([
Rule('/all/',defaults={'page':1},endpoint='all_entries'),
Rule('/all/page/<int:page>',endpoint='all_entries')
])
当访问http://example.com/all/page/1 时,将被重定向到http://example.com/all/。
subdomain:如何没有指定的话,采用map中的default_subdomain,如果map没有被绑定到subdomain,那么这个特性将不能使用
如果在不同的子域有不同的用户配置文件,而所有的子域都会转发到你的应用上,那么该选项将十分有用。
如:
url_map = Map([
Rule('/', subdomain='<username>', endpoint='user/homepage'),
Rule('/stats', subdomain='<username>', endpoint='user/stats')
])
methods:与前面介绍的**options中的methods一样
strict_slashes:当设置时,将覆盖掉Map中的设置。与唯一的URL/重定向行为中描述的问题一样。
build_only:Set this to True and the rule will never match but will create a URL that can be build. This is useful if you have resources on a subdomain or folder that are not handled by the WSGI application (like static data) ---不明白
redirect_to:当需要设置时,那么必须是字符串或者是回调函数。当是回调函数时,该函数需要将url适配器和URL值作为参数,并且返回重定向的URL。当是字符串时,为一个URL rule。
如:
def foo_with_slug(adapter, id):
# ask the database for the slug for the old id. this of
# course has nothing to do with werkzeug.
return 'foo/' + Foo.get_slug_for_id(id)
url_map = Map([
Rule('/foo/<slug>', endpoint='foo'),
Rule('/some/old/url/<slug>', redirect_to='foo/<slug>'),
Rule('/other/old/url/<int:id>', redirect_to=foo_with_slug)])
重定向的URL将以该域的root路径为起点,所以,不要使用前斜杠,除非你知道该域的root路径。
alias:别名
host:当设置后,那么URL map将为所有的host提供了一个匹配规则。
视图函数选项:(视图函数的属性)
__name__:视图函数的名称,默认作为endpoint。
methods:当在添加URL规则时,method没有被添加,可用该属性添加
provide_automatic_options:设置为True时,强制自动实现HTTP 的OPTIONS响应。
required_methods:当设置该选项后,当注册URL时,就会将这些方法加上。(不太懂)
如:
def index():
if request.method == 'OPTIONS':
# custom options handling here
...
return 'Hello World!'
index.provide_automatic_options = False
index.methods = ['GET', 'OPTIONS']
app.add_url_rule('/', index)