From fcfca6ec251004a49f36454878857b94449bb3c9 Mon Sep 17 00:00:00 2001 From: Pavel Kral Date: Thu, 27 Jul 2023 16:47:12 +0200 Subject: [PATCH 1/2] Implement tests for HTTPMethod from Python 3.11 --- tests/test_decorators.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 99ba13e60c..8d0805cbba 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -1,3 +1,5 @@ +import sys + import pytest from django.test import TestCase @@ -187,6 +189,20 @@ def test_action(request): assert str(excinfo.value) == "@action() missing required argument: 'detail'" + @pytest.mark.skipif(sys.version_info < (3, 11), reason="HTTPMethod was added in Python 3.11") + def test_method_mapping_http_method(self): + from http import HTTPMethod + + method_names = [getattr(HTTPMethod, name.upper()) for name in APIView.http_method_names] + + @action(detail=False, methods=method_names) + def test_action(): + raise NotImplementedError + + expected_mapping = {name: test_action.__name__ for name in APIView.http_method_names} + + assert test_action.mapping == expected_mapping + def test_method_mapping_http_methods(self): # All HTTP methods should be mappable @action(detail=False, methods=[]) From e1119f2d9a23534cdb42f9b1373ea8f13de8a462 Mon Sep 17 00:00:00 2001 From: Pavel Kral Date: Fri, 11 Aug 2023 11:34:19 +0200 Subject: [PATCH 2/2] Update documentation to mention HTTPMethod support in @action --- docs/api-guide/viewsets.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index 5d5491a83f..39db18bca1 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -178,6 +178,13 @@ The `action` decorator will route `GET` requests by default, but may also accept def unset_password(self, request, pk=None): ... +Argument `methods` also supports HTTP methods defined as [HTTPMethod](https://docs.python.org/3/library/http.html#http.HTTPMethod). Example below is identical to the one above: + + from http import HTTPMethod + + @action(detail=True, methods=[HTTPMethod.POST, HTTPMethod.DELETE]) + def unset_password(self, request, pk=None): + ... The decorator allows you to override any viewset-level configuration such as `permission_classes`, `serializer_class`, `filter_backends`...: