def do_teardown_request(
self,
exc: BaseException | None = _sentinel, # type: ignore[assignment]
) -> None:
"""Called after the request is dispatched and the response is
returned, right before the request context is popped.
This calls all functions decorated with
:meth:`teardown_request`, and :meth:`Blueprint.teardown_request`
if a blueprint handled the request. Finally, the
:data:`request_tearing_down` signal is sent.
This is called by
:meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`,
which may be delayed during testing to maintain access to
resources.
:param exc: An unhandled exception raised while dispatching the
request. Detected from the current exception information if
not passed. Passed to each teardown function.
.. versionchanged:: 0.9
Added the ``exc`` argument.
"""
if exc is _sentinel:
exc = sys.exc_info()[1]
for name in chain(request.blueprints, (None,)):
if name in self.teardown_request_funcs:
for func in reversed(self.teardown_request_funcs[name]):
self.ensure_sync(func)(exc)
request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
这段代码是 Flask 框架中的一个方法,该方法名为 do_teardown_request
。它是在请求处理完成、响应返回之后,请求上下文被弹出之前调用的。
如果传递了 exc
参数,则将其赋给传递的异常,否则从当前的异常信息中获取。然后,方法遍历了请求上下文中涉及的蓝图(Blueprints),并按照逆序执行与请求拆除相关的函数。最后,发送了 request_tearing_down
信号,其中包括 exc
参数。
这段代码的作用是在请求处理的最后阶段执行用于清理资源或处理异常的函数,并发送相应的信号通知其他相关模块。
同时,这段代码展示了在 Flask 框架中如何进行资源清理和异常处理的一般实现方式。
def do_teardown_appcontext(
self,
exc: BaseException | None = _sentinel, # type: ignore[assignment]
) -> None:
"""Called right before the application context is popped.
When handling a request, the application context is popped
after the request context. See :meth:`do_teardown_request`.
This calls all functions decorated with
:meth:`teardown_appcontext`. Then the
:data:`appcontext_tearing_down` signal is sent.
This is called by
:meth:`AppContext.pop() <flask.ctx.AppContext.pop>`.
.. versionadded:: 0.9
"""
if exc is _sentinel:
exc = sys.exc_info()[1]
for func in reversed(self.teardown_appcontext_funcs):
self.ensure_sync(func)(exc)
appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
这段代码是Flask应用程序在弹出应用程序上下文之前调用的方法。在处理请求时,应用程序上下文会在请求上下文之后弹出。
在该方法中:
- 如果没有传入异常(exc),则会使用sys.exc_info()[1]获取异常。
- 然后,会调用所有装饰有teardown_appcontext的函数。
- 最后,会发送appcontext_tearing_down信号。
这段代码的主要功能是在应用程序上下文被弹出之前执行必要的清理操作,包括调用已装饰的teardown_appcontext函数和发送appcontext_tearing_down信号。
def app_context(self) -> AppContext:
"""Create an :class:`~flask.ctx.AppContext`. Use as a ``with``
block to push the context, which will make :data:`current_app`
point at this application.
An application context is automatically pushed by
:meth:`RequestContext.push() <flask.ctx.RequestContext.push>`
when handling a request, and when running a CLI command. Use
this to manually create a context outside of these situations.
::
with app.app_context():
init_db()
See :doc:`/appcontext`.
.. versionadded:: 0.9
"""
return AppContext(self)
def request_context(self, environ: WSGIEnvironment) -> RequestContext:
"""Create a :class:`~flask.ctx.RequestContext` representing a
WSGI environment. Use a ``with`` block to push the context,
which will make :data:`request` point at this request.
See :doc:`/reqcontext`.
Typically you should not call this from your own code. A request
context is automatically pushed by the :meth:`wsgi_app` when
handling a request. Use :meth:`test_request_context` to create
an environment and context instead of this method.
:param environ: a WSGI environment
"""
return RequestContext(self, environ)
这段代码定义了两个方法:app_context
和request_context
。这两个方法用于创建应用程序上下文(AppContext
)和请求上下文(RequestContext
)。
app_context
方法返回一个应用程序上下文对象,可以使用with
语句将上下文推送到当前应用程序,从而使current_app
指向这个应用程序。应用程序上下文会在处理请求时和运行CLI命令时自动推送,也可以在这些情况之外手动创建上下文。
request_context
方法接受一个WSGI环境作为参数,并返回一个代表该环境的请求上下文对象。与app_context
类似,可以使用with
语句将请求上下文推送到当前应用程序,从而使request
指向该请求。一般情况下,不需要直接调用这个方法,因为请求上下文会在处理请求时由wsgi_app
自动推送,可以使用test_request_context
方法来创建环境和上下文。
def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext:
"""Create a :class:`~flask.ctx.RequestContext` for a WSGI
environment created from the given values. This is mostly useful
during testing, where you may want to run a function that uses
request data without dispatching a full request.
See :doc:`/reqcontext`.
Use a ``with`` block to push the context, which will make
:data:`request` point at the request for the created
environment. ::
with app.test_request_context(...):
generate_report()
When using the shell, it may be easier to push and pop the
context manually to avoid indentation. ::
ctx = app.test_request_context(...)
ctx.push()
...
ctx.pop()
Takes the same arguments as Werkzeug's
:class:`~werkzeug.test.EnvironBuilder`, with some defaults from
the application. See the linked Werkzeug docs for most of the
available arguments. Flask-specific behavior is listed here.
:param path: URL path being requested.
:param base_url: Base URL where the app is being served, which
``path`` is relative to. If not given, built from
:data:`PREFERRED_URL_SCHEME`, ``subdomain``,
:data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
:param subdomain: Subdomain name to append to
:data:`SERVER_NAME`.
:param url_scheme: Scheme to use instead of
:data:`PREFERRED_URL_SCHEME`.
:param data: The request body, either as a string or a dict of
form keys and values.
:param json: If given, this is serialized as JSON and passed as
``data``. Also defaults ``content_type`` to
``application/json``.
:param args: other positional arguments passed to
:class:`~werkzeug.test.EnvironBuilder`.
:param kwargs: other keyword arguments passed to
:class:`~werkzeug.test.EnvironBuilder`.
"""
from .testing import EnvironBuilder
builder = EnvironBuilder(self, *args, **kwargs)
try:
return self.request_context(builder.get_environ())
finally:
builder.close()
这段代码定义了一个名为test_request_context
的方法。它允许从给定值创建的WSGI环境创建一个flask.ctx.RequestContext
。这在测试过程中非常有用,可以运行使用请求数据而不需要派发完整请求的函数。通过使用with
语句推送上下文,可以使request
指向为创建的环境的请求。该方法采用与Werkzeug的werkzeug.test.EnvironBuilder
相同的参数,并在应用程序中具有一些默认值。在flask.ctx.RequestContext
上下文中返回环境构建器的结果。并在完成后关闭环境构建器。主要功能是为了方便在测试中创建一个包含请求数据的环境,以便在不派发完整请求的情况下运行函数。通过这种方式,您可以模拟请求上下文并进行测试,而无需实际发送HTTP请求。
def wsgi_app(
self, environ: WSGIEnvironment, start_response: StartResponse
) -> cabc.Iterable[bytes]:
"""The actual WSGI application. This is not implemented in
:meth:`__call__` so that middlewares can be applied without
losing a reference to the app object. Instead of doing this::
app = MyMiddleware(app)
It's a better idea to do this instead::
app.wsgi_app = MyMiddleware(app.wsgi_app)
Then you still have the original application object around and
can continue to call methods on it.
.. versionchanged:: 0.7
Teardown events for the request and app contexts are called
even if an unhandled error occurs. Other events may not be
called depending on when an error occurs during dispatch.
See :ref:`callbacks-and-errors`.
:param environ: A WSGI environment.
:param start_response: A callable accepting a status code,
a list of headers, and an optional exception context to
start the response.
"""
ctx = self.request_context(environ)
error: BaseException | None = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except: # noqa: B001
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if "werkzeug.debug.preserve_context" in environ:
environ["werkzeug.debug.preserve_context"](_cv_app.get())
environ["werkzeug.debug.preserve_context"](_cv_request.get())
if error is not None and self.should_ignore_error(error):
error = None
ctx.pop(error)
def __call__(
self, environ: WSGIEnvironment, start_response: StartResponse
) -> cabc.Iterable[bytes]:
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app`, which can be
wrapped to apply middleware.
"""
return self.wsgi_app(environ, start_response)
这段代码定义了wsgi_app
方法和__call__
方法,用于处理WSGI(Web Server Gateway Interface)请求。在WSGI应用中,__call__
方法被WSGI服务器调用,然后调用wsgi_app
方法来处理请求。以下是主要功能:
-
wsgi_app
方法负责处理WSGI请求:- 通过
request_context
方法创建请求上下文。 - 尝试调用
full_dispatch_request
方法处理请求。如果发生异常,则调用handle_exception
方法处理异常。 - 最终返回响应。
- 在处理完成后,检查是否需要忽略错误并弹出请求上下文。
- 通过
-
__call__
方法作为WSGI应用的入口点,被WSGI服务器调用,然后委派给wsgi_app
方法来处理请求。
这段代码实现了Flask应用的WSGI处理逻辑,负责处理请求和响应,并在必要时调用异常处理逻辑。