- WSGI入门笔记:WSGI入门
- Flask入门一:Flask入门与routing机制(wekzeug)
- Flask入门二:Flask模板与Jinja
- Flask入门三:Flask获取HTTP请求数据
- Flask入门四:Flask应用配置与routing中的subdomain
- Flask入门五:Flask路由之endpoint参数
接触flask这几天,一直在遇到endpoint 这个东西。不能一直跳过它...
endpoint
例子
在前面,一直在使用装饰器route()
:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hello World!"
这个写法等价于显式使用endpoint
的:
from flask import Flask
app = Flask(__name__)
@app.route('/', endpoint='index')
def index():
return "Hello World!"
如果不用装饰器,也可以用add_url_rule
写成:
from flask import Flask
app = Flask(__name__)
def index():
return "Hello World!"
app.add_url_rule('/', 'index', index)
更容易理解的,可能是写成这样?:
from flask import Flask
app = Flask(__name__)
def index():
return "Hello World!"
app.add_url_rule('/', 'index')
app.view_functions['index'] = index
从这儿可以看到:
- URL rule 和 endpoint 是一组
- endpoint 和
view_func
函数 是另一组
route() 参数
而不管装饰器route
,还是函数add_url_rule
,都接收如下参数:
- rule:URL规则
- endpoint:一个字符串,代表URL规则。Flask默认使用
view_func
的名字作为endpoint。 view_func
:endpoint对应的view_func
。一个view_func
可以对应多个endpoint。装饰器route()不用指定这个参数,会自动生成。add_rul_rule()
如果不指定,需要手动修改view_functions
将其加入进去。- defaults:一个dict,为变量定义默认值。
- subdomain:子域名,与应用配置
SERVER_NAME
相关。 **options
:其他选项,传递给Rule对象,通过关键字参数指定。常用的有 method。
url_map 与 view_functions
Flask内部维护了两张表:
url_map
:url与endpoint的关系view_functions
:endpoint与function的关系
要作为view_functions
的key,endpoint需要是唯一的(等同于一个标识符)。多个不同的endpoint可以对应同一个view_func
。
看一个例子
from flask import Flask
app = Flask(__name__)
@app.route('/')
@app.route('/debao')
def index():
return "Hello World!"
print(app.url_map)
print(app.view_functions)
其控制台,结果:
Map([<Rule '/static/<filename>' (GET, HEAD, OPTIONS) -> static>,
<Rule '/debao' (GET, HEAD, OPTIONS) -> index>,
<Rule '/' (GET, HEAD, OPTIONS) -> index>])
{'static': <function Flask.__init__.<locals>.<lambda> at 0x000001CBABC6DBC0>, 'index': <function index at 0x000001CBAE6E7600>}
从这儿可以看到:
- URL到"index"这个endpoint有两个规则
-
"index"这个endpoint到view有一个规则
-
flask有夹带私货:把静态资源static 规则默认添加进去了
url_for()
这个函数接收的第一个参数是 endpoint。用于反向构建URL字符串。
url_for(endpoint, *, _anchor=None, _method=None, _scheme=None, _external=None, **values)
这个函数也挺复杂,受SERVER_NAME
等一堆东西影响...
Werkzeug
Werkzeug,/ˈvɛrkʦɔyk/,德语,工具的意思。好吧,已经好几天了,看着音标我还是不会发这个音。
其实到现在为止,我还是没理解到endpoint的设计精髓,只是看到它把URL和对应处理函数view_func
的映射拆成两部分,有助于解耦。
换个角度看:URL到 endpoint的映射,是wekzeug框架的内容;而endpoint到view函数的映射,是属于Flask自己内容。真要找答案,后面需要了解werkzeug才行
from werkzeug.routing import Map, Rule
url_map = Map([
Rule('/', endpoint='blog/index'),
Rule('/<int:year>/', endpoint='blog/archive'),
Rule('/<int:year>/<int:month>/', endpoint='blog/archive'),
Rule('/<int:year>/<int:month>/<int:day>/', endpoint='blog/archive'),
Rule('/about', endpoint='blog/about_me'),
Rule('/feeds/', endpoint='blog/feeds'),
Rule('/feeds/<feed_name>.rss', endpoint='blog/show_feed')
])
回到flask,还可以这么玩(先建立URL和endpoint关系,再使用endpoint装饰器):
from flask import Flask
from werkzeug.routing import Rule
app = Flask(__name__)
app.url_map.add(Rule('/', endpoint='index'))
@app.endpoint('index')
def my_index():
return "Hello world"
参考
- https://github.com/pallets/flask
- https://flask.palletsprojects.com
- https://werkzeug.palletsprojects.com/en/3.0.x/routing/