從app.route裝飾器引發對endpoint的思考
從app.route裝飾器引發對endpoint的思考
還是先來看看原始碼
def route(self, rule, **options): """A decorator that is used to register a view function for a given URL rule. This does the same thing as :meth:`add_url_rule` but is intended for decorator usage:: @app.route('/') def index(): return 'Hello World' For more information refer to :ref:`url-route-registrations`. :param rule: the URL rule as string :param endpoint: the endpoint for the registered URL rule. Flask itself assumes the name of the view function as endpoint :param options: the options to be forwarded to the underlying :class:`~werkzeug.routing.Rule` object. A change to Werkzeug is handling of method options. methods is a list of methods this rule should be limited to (``GET``, ``POST`` etc.). By default a rule just listens for ``GET`` (and implicitly ``HEAD``). Starting with Flask 0.6, ``OPTIONS`` is implicitly added and handled by the standard request handling. """ def decorator(f): endpoint = options.pop('endpoint', None) self.add_url_rule(rule, endpoint, f, **options) return f return decorator
route傳入了**options這樣一個字典,一般我們會傳方法methods進去,GET、POST,如果不自己設定endpoint=....的話預設就是No。
然後進入add_url_rule函式看一看:
def add_url_rule(self, rule, endpoint=None, view_func=None, **options): if endpoint is None: endpoint = _endpoint_from_view_func(view_func) options['endpoint'] = endpoint methods = options.pop('methods', None) ... ... ... self.url_map.add(rule) if view_func is not None: old_func = self.view_functions.get(endpoint) if old_func is not None and old_func != view_func: raise AssertionError('View function mapping is overwriting an ' 'existing endpoint function: %s' % endpoint) self.view_functions[endpoint] = view_func
這裡我截取了一些重點的,可以看到如果endpoint為None,會呼叫_endpoint_from_view_func函式來給endpoint賦值,
看一下_endpoint_from_view_func的程式碼:
def _endpoint_from_view_func(view_func): """Internal helper that returns the default endpoint for a given function. This always is the function name. """ assert view_func is not None, 'expected view func if endpoint ' \ 'is not provided.' return view_func.__name__
可以看到將檢視函式名賦值給了endpoint,所以如果我們建立檢視函式時不在**options中指明endpoint的話,預設就是檢視函式名,
後半部分進行了判斷,保證了endpoint的唯一,並將view_func儲存在view_functions這個字典中,並且和endpoint形成對映關係,還將路徑加入到當前應用中, 這樣做的好處是,當我們用url_for()從一個endpoint來找到一個URL時,可以順著這個對映關係來找,而不用寫URL, 常見的用法是url_for(blueprint.endpoint,parm=val...)進行重定向,這樣可以獲取一個檢視函式的路徑,傳給redirect(),
redirect(location,code=302)函式會把接收的引數作為響應body中的Location欄位返回給客戶端,並且預設是302臨時重定向。
def redirect(location, code=302, Response=None):
...
...
#為Location欄位賦值,返回給客戶端進行重定向
response.headers['Location'] = location
return response
總結:
URL《————》endpoint《————》view
一個檢視函式的endpoint如果不設定那麼就是檢視函式名。
為URL和view搭起橋樑,使得整個後端框架更加靈活。
url_for(.endpoint)返回的是檢視函式對應的URL,URL是對應檢視函式裝飾器傳入的值。