add redirect method to app

This commit is contained in:
Tim Hoagland 2022-05-02 12:44:15 -04:00 committed by David Lord
parent bd56d19b16
commit fdab801fbb
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
5 changed files with 55 additions and 1 deletions

View file

@ -5,6 +5,9 @@ Version 2.2.0
Unreleased Unreleased
- Add an ``app.redirect`` method, which ``flask.redirect`` will call.
This makes it possible for an app to override how redirects work.
:issue:`4569`
- Refactor ``register_error_handler`` to consolidate error checking. - Refactor ``register_error_handler`` to consolidate error checking.
Rewrite some error messages to be more consistent. :issue:`4559` Rewrite some error messages to be more consistent. :issue:`4559`

View file

@ -1,7 +1,6 @@
from markupsafe import escape from markupsafe import escape
from markupsafe import Markup from markupsafe import Markup
from werkzeug.exceptions import abort as abort from werkzeug.exceptions import abort as abort
from werkzeug.utils import redirect as redirect
from . import json as json from . import json as json
from .app import Flask as Flask from .app import Flask as Flask
@ -23,6 +22,7 @@ from .helpers import flash as flash
from .helpers import get_flashed_messages as get_flashed_messages from .helpers import get_flashed_messages as get_flashed_messages
from .helpers import get_template_attribute as get_template_attribute from .helpers import get_template_attribute as get_template_attribute
from .helpers import make_response as make_response from .helpers import make_response as make_response
from .helpers import redirect as redirect
from .helpers import send_file as send_file from .helpers import send_file as send_file
from .helpers import send_from_directory as send_from_directory from .helpers import send_from_directory as send_from_directory
from .helpers import stream_with_context as stream_with_context from .helpers import stream_with_context as stream_with_context

View file

@ -22,6 +22,7 @@ from werkzeug.routing import MapAdapter
from werkzeug.routing import RequestRedirect from werkzeug.routing import RequestRedirect
from werkzeug.routing import RoutingException from werkzeug.routing import RoutingException
from werkzeug.routing import Rule from werkzeug.routing import Rule
from werkzeug.utils import redirect as _wz_redirect
from werkzeug.wrappers import Response as BaseResponse from werkzeug.wrappers import Response as BaseResponse
from . import cli from . import cli
@ -1630,6 +1631,16 @@ class Flask(Scaffold):
return asgiref_async_to_sync(func) return asgiref_async_to_sync(func)
def redirect(self, location: str, code: int = 302) -> BaseResponse:
"""Create a redirect response object.
:param location: the url of the redirect
:param code: http return code
.. versionadded:: 2.2
"""
return _wz_redirect(location, code=code, Response=self.response_class)
def make_response(self, rv: ResponseReturnValue) -> Response: def make_response(self, rv: ResponseReturnValue) -> Response:
"""Convert the return value from a view function to an instance of """Convert the return value from a view function to an instance of
:attr:`response_class`. :attr:`response_class`.

View file

@ -12,6 +12,7 @@ from threading import RLock
import werkzeug.utils import werkzeug.utils
from werkzeug.routing import BuildError from werkzeug.routing import BuildError
from werkzeug.urls import url_quote from werkzeug.urls import url_quote
from werkzeug.utils import redirect as _wz_redirect
from .globals import _app_ctx_stack from .globals import _app_ctx_stack
from .globals import _request_ctx_stack from .globals import _request_ctx_stack
@ -21,6 +22,7 @@ from .globals import session
from .signals import message_flashed from .signals import message_flashed
if t.TYPE_CHECKING: # pragma: no cover if t.TYPE_CHECKING: # pragma: no cover
from werkzeug.wrappers import Response as BaseResponse
from .wrappers import Response from .wrappers import Response
@ -340,6 +342,28 @@ def url_for(endpoint: str, **values: t.Any) -> str:
return rv return rv
def redirect(
location: str, code: int = 302, Response: t.Optional[t.Type["BaseResponse"]] = None
) -> "BaseResponse":
"""Create a redirect response object.
If :data:`~flask.current_app` is available, it will use
:meth:`~flask.app.Flask.redirect`, otherwise it will use
:func:`werkzeug.utils.redirect`.
:param location: The URL to redirect to.
:param code: The status code for the redirect.
:param Response: The response class to use. Not used when
``current_app`` is active, which uses ``app.response_class``.
.. versionadded:: 2.2
"""
if current_app:
return current_app.redirect(location, code=code)
return _wz_redirect(location, code=code, Response=Response)
def get_template_attribute(template_name: str, attribute: str) -> t.Any: def get_template_attribute(template_name: str, attribute: str) -> t.Any:
"""Loads a macro (or variable) a template exports. This can be used to """Loads a macro (or variable) a template exports. This can be used to
invoke a macro from within Python code. If you for example have a invoke a macro from within Python code. If you for example have a

View file

@ -158,6 +158,22 @@ class TestUrlFor:
assert flask.url_for("myview", _method="POST") == "/myview/create" assert flask.url_for("myview", _method="POST") == "/myview/create"
def test_redirect_no_app():
response = flask.redirect("https://localhost", 307)
assert response.location == "https://localhost"
assert response.status_code == 307
def test_redirect_with_app(app):
def redirect(location, code=302):
raise ValueError
app.redirect = redirect
with app.app_context(), pytest.raises(ValueError):
flask.redirect("other")
class TestNoImports: class TestNoImports:
"""Test Flasks are created without import. """Test Flasks are created without import.