Flask 탐색2(app.route 내부 구현)
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
전편 블로그는flask의 각 매개 변수의 작용을 탐구하였으며, 본편은 @app를 둘러싸고 있습니다.route('/') flask가 뭘 했는지 탐구해 보세요.
route 방법
route 소스
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는 사실상 폐쇄적인 패키지입니다. 경로 규칙은route 방법을 통해rule형참에 인용된 다음decorator 방법을 되돌려줍니다. 그래서 @ app입니다.route('/')<==>@decorator, 그래서 helloworld =decorator (hello_world ) <==> hello_world . @app.route('/')의 주작은endpoint = options.pop('endpoint', None) 및 self.add_url_rule(rule,endpoint,f,**options) 두 마디.
add_url_rule
add_url_rule 소스
@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None,
provide_automatic_options=None, **options):
"""Connects a URL rule. Works exactly like the :meth:`route`
decorator. If a view_func is provided it will be registered with the
endpoint.
Basically this example::
@app.route('/')
def index():
pass
Is equivalent to the following::
def index():
pass
app.add_url_rule('/', 'index', index)
If the view_func is not provided you will need to connect the endpoint
to a view function like so::
app.view_functions['index'] = index
Internally :meth:`route` invokes :meth:`add_url_rule` so if you want
to customize the behavior via subclassing you only need to change
this method.
For more information refer to :ref:`url-route-registrations`.
.. versionchanged:: 0.2
`view_func` parameter added.
.. versionchanged:: 0.6
``OPTIONS`` is added automatically as method.
: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 view_func: the function to call when serving a request to the
provided endpoint
:param provide_automatic_options: controls whether the ``OPTIONS``
method should be added automatically. This can also be controlled
by setting the ``view_func.provide_automatic_options = False``
before adding the rule.
: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.
"""
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None)
# if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
# Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ()))
# starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None)
if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False
# Add the required methods now.
methods |= required_methods
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
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
다른 바인딩 방식
방법 주석에서 url 규칙과 함수를 연결할 수 있는 다른 방식을 볼 수 있다
@app.route('/')
def index():
pass
#
def index():
pass
# add_url_rule(url , , )
app.add_url_rule('/', 'index', index)
분석하다.
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None)
장식기를 통해 경로를 등록하면 일반적으로 endpoint는 None과 같기 때문에 endpoint=endpoint_from_view_func(view_func).
_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_from_view_func 방법, endpoint = viewfunc.__name__, 장식기를 통해 경로를 등록할 수 있으며, 일반적인 경우endpoint는 방법명과 같습니다.
분석하다.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
실험 일반상황에서viewfunc는methods 속성이 없습니다. 원본 코드를 수정하여 원본 코드를 실험하기 편리합니다
#
print(endpoint + " #" * 20)
# methods
print(methods)
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
# methods
print(methods)
#
print(endpoint + " #" * 20)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
demo.py
@app.route('/')
def index():
return 'index'
@app.route('/', methods=["POST"])
def index1():
return 'index'
@app.route('/', methods=["POST", "GET"])
def index2():
return 'index'
실험 결과
static # # # # # # # # # # # # # # # # # # # #
None
('GET',)
static # # # # # # # # # # # # # # # # # # # #
index # # # # # # # # # # # # # # # # # # # #
None
('GET',)
index # # # # # # # # # # # # # # # # # # # #
index1 # # # # # # # # # # # # # # # # # # # #
['POST']
['POST']
index1 # # # # # # # # # # # # # # # # # # # #
index2 # # # # # # # # # # # # # # # # # # # #
['POST', 'GET']
['POST', 'GET']
index2 # # # # # # # # # # # # # # # # # # # #
위의 결과를 통해 알 수 있다
분석하다.
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
이 두 마디를 통해 methods는 키 값을 통해 형식에 값을 부여하고 methods="POST"의 형식을 제외한 모든 교체 가능한 용기는 값으로 할 수 있다는 결론을 얻을 수 있다.
분석하다.
원본 코드
# Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ()))
# starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None)
if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False
# Add the required methods now.
methods |= required_methods
실험 원본 코드 개조
# Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ()))
# starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None)
if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False
# --------------------------------------
print("methods ", methods)
print("required_methods ", required_methods)
# Add the required methods now.
methods |= required_methods
print("methods ", methods)
print("required_methods ", required_methods)
print("*" * 20)
demo.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/', methods=("POST", "GET"))
def index2():
return 'index'
if __name__ == '__main__':
app.run(debug=True)
결실
methods {'GET'}
required_methods {'OPTIONS'}
methods {'OPTIONS', 'GET'}
required_methods {'OPTIONS'}
********************
methods {'GET'}
required_methods {'OPTIONS'}
methods {'OPTIONS', 'GET'}
required_methods {'OPTIONS'}
********************
methods {'POST', 'GET'}
required_methods {'OPTIONS'}
methods {'POST', 'OPTIONS', 'GET'}
required_methods {'OPTIONS'}
********************
실험을 통해 알 수 있듯이,
분석하다.
원본 코드
# rule
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
# rule Map
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
실험 원본 코드 변경
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule)
if view_func is not None:
print("%-10s %s" % ("endpoint", endpoint))
old_func = self.view_functions.get(endpoint)
print("%-20s %s" % ("old_func is not None", old_func is not None))
print("%-20s %s" % ("old_func != view_func", old_func != view_func))
print()
print("*" * 20)
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
demo.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
#
app.add_url_rule("/", "index", index)
app.add_url_rule("/", "index2", index)
if __name__ == '__main__':
app.run(debug=True)
실험 결과
#
endpoint static
old_func is not None False
old_func != view_func True
********************
#
endpoint index
old_func is not None False
old_func != view_func True
********************
#
endpoint index
old_func is not None True
old_func != view_func False
********************
#
endpoint index2
old_func is not None False
old_func != view_func True
********************
요약:
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.