pass positional arguments to class-based views (Fixes #5199)

This commit is contained in:
Miguel Grinberg 2023-07-15 23:49:42 +01:00
parent cb825687a5
commit b6c3569c5e
No known key found for this signature in database
3 changed files with 43 additions and 7 deletions

View file

@ -7,7 +7,7 @@ Unreleased
- Require Werkzeug >= 2.3.6.
- Use ``flit_core`` instead of ``setuptools`` as build backend.
- Refactor how an app's root and instance paths are determined. :issue:`5160`
- Pass positional arguments to class-based views. :issue:`5199`
Version 2.3.2
-------------

View file

@ -102,17 +102,17 @@ class View:
"""
if cls.init_every_request:
def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
def view(*args: t.Any, **kwargs: t.Any) -> ft.ResponseReturnValue:
self = view.view_class( # type: ignore[attr-defined]
*class_args, **class_kwargs
)
return current_app.ensure_sync(self.dispatch_request)(**kwargs)
return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
else:
self = cls(*class_args, **class_kwargs)
def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
return current_app.ensure_sync(self.dispatch_request)(**kwargs)
def view(*args: t.Any, **kwargs: t.Any) -> ft.ResponseReturnValue:
return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
if cls.decorators:
view.__name__ = name
@ -178,7 +178,7 @@ class MethodView(View):
if methods:
cls.methods = methods
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
def dispatch_request(self, *args: t.Any, **kwargs: t.Any) -> ft.ResponseReturnValue:
meth = getattr(self, request.method.lower(), None)
# If the request method is HEAD and we don't have a handler for it
@ -187,4 +187,4 @@ class MethodView(View):
meth = getattr(self, "get", None)
assert meth is not None, f"Unimplemented method {request.method!r}"
return current_app.ensure_sync(meth)(**kwargs)
return current_app.ensure_sync(meth)(*args, **kwargs)

View file

@ -98,6 +98,42 @@ def test_view_decorators(app, client):
assert rv.data == b"Awesome"
def test_view_decorators_with_injected_args(app, client):
def add_arg(f):
def new_function(*args, **kwargs):
return f("Awesome", *args, **kwargs)
return new_function
class Index(flask.views.View):
decorators = [add_arg]
def dispatch_request(self, arg):
return arg
app.add_url_rule("/", view_func=Index.as_view("index"))
rv = client.get("/")
assert rv.data == b"Awesome"
def test_method_based_view_decorators_with_injected_args(app, client):
def add_arg(f):
def new_function(*args, **kwargs):
return f("Awesome", *args, **kwargs)
return new_function
class Index(flask.views.MethodView):
decorators = [add_arg]
def post(self, arg):
return arg
app.add_url_rule("/", view_func=Index.as_view("index"))
rv = client.post("/")
assert rv.data == b"Awesome"
def test_view_provide_automatic_options_attr():
app = flask.Flask(__name__)