mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-04-25 19:43:47 +03:00
Schema: Exclude OPTIONS/HEAD for ViewSet actions (#5532)
Closes #5528. Viewset custom actions (@detail_route etc) OPTIONS (and HEAD) methods were not being excluded from Schema Generations. This PR adds a test reproducing the reported error and adjusts `EndpointEnumerator.get_allowed_methods()` to filter ViewSet actions in the same way as other `APIView`s
This commit is contained in:
parent
efb047fa07
commit
7261ae653a
|
@ -222,12 +222,11 @@ class EndpointEnumerator(object):
|
||||||
if hasattr(callback, 'actions'):
|
if hasattr(callback, 'actions'):
|
||||||
actions = set(callback.actions.keys())
|
actions = set(callback.actions.keys())
|
||||||
http_method_names = set(callback.cls.http_method_names)
|
http_method_names = set(callback.cls.http_method_names)
|
||||||
return [method.upper() for method in actions & http_method_names]
|
methods = [method.upper() for method in actions & http_method_names]
|
||||||
|
else:
|
||||||
|
methods = callback.cls().allowed_methods
|
||||||
|
|
||||||
return [
|
return [method for method in methods if method not in ('OPTIONS', 'HEAD')]
|
||||||
method for method in
|
|
||||||
callback.cls().allowed_methods if method not in ('OPTIONS', 'HEAD')
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SchemaGenerator(object):
|
class SchemaGenerator(object):
|
||||||
|
|
|
@ -901,3 +901,53 @@ def test_is_list_view_recognises_retrieve_view_subclasses():
|
||||||
|
|
||||||
is_list = is_list_view(path, method, view)
|
is_list = is_list_view(path, method, view)
|
||||||
assert not is_list, "RetrieveAPIView subclasses should not be classified as list views."
|
assert not is_list, "RetrieveAPIView subclasses should not be classified as list views."
|
||||||
|
|
||||||
|
|
||||||
|
def test_head_and_options_methods_are_excluded():
|
||||||
|
"""
|
||||||
|
Regression test for #5528
|
||||||
|
https://github.com/encode/django-rest-framework/issues/5528
|
||||||
|
|
||||||
|
Viewset OPTIONS actions were not being correctly excluded
|
||||||
|
|
||||||
|
Initial cases here shown to be working as expected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@api_view(['options', 'get'])
|
||||||
|
def fbv(request):
|
||||||
|
pass
|
||||||
|
|
||||||
|
inspector = EndpointEnumerator()
|
||||||
|
|
||||||
|
path = '/a/path/'
|
||||||
|
callback = fbv
|
||||||
|
|
||||||
|
assert inspector.should_include_endpoint(path, callback)
|
||||||
|
assert inspector.get_allowed_methods(callback) == ["GET"]
|
||||||
|
|
||||||
|
class AnAPIView(APIView):
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def options(self, request, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
callback = AnAPIView.as_view()
|
||||||
|
|
||||||
|
assert inspector.should_include_endpoint(path, callback)
|
||||||
|
assert inspector.get_allowed_methods(callback) == ["GET"]
|
||||||
|
|
||||||
|
class AViewSet(ModelViewSet):
|
||||||
|
|
||||||
|
@detail_route(methods=['options', 'get'])
|
||||||
|
def custom_action(self, request, pk):
|
||||||
|
pass
|
||||||
|
|
||||||
|
callback = AViewSet.as_view({
|
||||||
|
"options": "custom_action",
|
||||||
|
"get": "custom_action"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert inspector.should_include_endpoint(path, callback)
|
||||||
|
assert inspector.get_allowed_methods(callback) == ["GET"]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user