# ============== 对请求方法进行处理 开始 ============== if methods isNone: methods = getattr(view_func, "methods", None) or ("GET",) ifisinstance(methods, str): raise TypeError( "Allowed methods must be a list of strings, for" ' example: @app.route(..., methods=["POST"])' ) methods = {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 isNone: provide_automatic_options = getattr( view_func, "provide_automatic_options", None )
defview(**kwargs: t.Any) -> ft.ResponseReturnValue: return current_app.ensure_sync(self.dispatch_request)(**kwargs) # CBV 的装饰器处理方式 if cls.decorators: view.__name__ = name view.__module__ = cls.__module__ for decorator in cls.decorators: view = decorator(view)
# We attach the view class to the view function for two reasons: # first of all it allows us to easily figure out what class-based # view this thing came from, secondly it's also used for instantiating # the view class so you can actually replace it with something else # for testing purposes and debugging. view.view_class = cls # type: ignore view.__name__ = name view.__doc__ = cls.__doc__ view.__module__ = cls.__module__ view.methods = cls.methods # type: ignore view.provide_automatic_options = cls.provide_automatic_options # type: ignore
defensure_sync(self, func: t.Callable) -> t.Callable: """Ensure that the function is synchronous for WSGI workers. Plain ``def`` functions are returned as-is. ``async def`` functions are wrapped to run and wait for the response. Override this method to change how the app runs async views. .. versionadded:: 2.0 """ if iscoroutinefunction(func): return self.async_to_sync(func)
# If the request method is HEAD and we don't have a handler for it # retry with GET. if meth isNoneand request.method == "HEAD": meth = getattr(self, "get", None)