Add syntatic sugar for route registration

This takes a popular API whereby instead of passing the HTTP method as
an argument to route it is instead used as the method name i.e.

    @app.route("/", methods=["POST"])

is now writeable as,

    @app.post("/")

This is simply syntatic sugar, it doesn't do anything else, but makes
it slightly easier for users.

I've included all the methods that are relevant and aren't auto
generated i.e. not connect, head, options, and trace.
This commit is contained in:
pgjones 2021-02-14 11:08:21 +00:00 committed by David Lord
parent 82d69cd06c
commit 705e52684a
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
3 changed files with 61 additions and 0 deletions

View File

@ -64,6 +64,9 @@ Unreleased
This could allow a session interface to change behavior based on
``request.endpoint``. :issue:`3776`
- Use Jinja's implementation of the ``|tojson`` filter. :issue:`3881`
- Add route decorators for common HTTP methods. For example,
``@app.post("/login")`` is a shortcut for
``@app.route("/login", methods=["POST"])``. :pr:`3907`
Version 1.1.2

View File

@ -146,6 +146,47 @@ class Scaffold(_PackageBoundObject):
def _is_setup_finished(self):
raise NotImplementedError
def _method_route(self, method, rule, options):
if "methods" in options:
raise TypeError("Use the 'route' decorator to use the 'methods' argument.")
return self.route(rule, methods=[method], **options)
def get(self, rule, **options):
"""Shortcut for :meth:`route` with ``methods=["GET"]``.
.. versionadded:: 2.0
"""
return self._method_route("GET", rule, options)
def post(self, rule, **options):
"""Shortcut for :meth:`route` with ``methods=["POST"]``.
.. versionadded:: 2.0
"""
return self._method_route("POST", rule, options)
def put(self, rule, **options):
"""Shortcut for :meth:`route` with ``methods=["PUT"]``.
.. versionadded:: 2.0
"""
return self._method_route("PUT", rule, options)
def delete(self, rule, **options):
"""Shortcut for :meth:`route` with ``methods=["DELETE"]``.
.. versionadded:: 2.0
"""
return self._method_route("DELETE", rule, options)
def patch(self, rule, **options):
"""Shortcut for :meth:`route` with ``methods=["PATCH"]``.
.. versionadded:: 2.0
"""
return self._method_route("PATCH", rule, options)
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`

View File

@ -48,6 +48,23 @@ def test_options_on_multiple_rules(app, client):
assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS", "POST", "PUT"]
@pytest.mark.parametrize("method", ["get", "post", "put", "delete", "patch"])
def test_method_route(app, client, method):
method_route = getattr(app, method)
client_method = getattr(client, method)
@method_route("/")
def hello():
return "Hello"
assert client_method("/").data == b"Hello"
def test_method_route_no_methods(app):
with pytest.raises(TypeError):
app.get("/", methods=["GET", "POST"])
def test_provide_automatic_options_attr():
app = flask.Flask(__name__)