從app.route裝飾器引發對endpoint的思考

JxBetter發表於2019-02-16

還是先來看看原始碼

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是對應檢視函式裝飾器傳入的值。

相關文章