diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 3d46251b99c..8794c9967c2 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -218,6 +218,10 @@ def should_include_endpoint(self, path, callback): if callback.cls.schema is None: return False + if 'schema' in callback.initkwargs: + if callback.initkwargs['schema'] is None: + return False + if path.endswith('.{format}') or path.endswith('.{format}/'): return False # Ignore .json style URLs. diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 5c9659a57d7..b90f60e084b 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -157,7 +157,8 @@ def __get__(self, instance, owner): def __set__(self, instance, other): self.instance_schemas[instance] = other - other.view = instance + if other is not None: + other.view = instance @property def view(self): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index d13f3f2585b..7f155b570b1 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -99,6 +99,10 @@ def custom_list_action(self, request): def custom_list_action_multiple_methods(self, request): return super(ExampleViewSet, self).list(self, request) + @action(detail=False, schema=None) + def excluded_action(self, request): + pass + def get_serializer(self, *args, **kwargs): assert self.request assert self.action @@ -737,6 +741,19 @@ def extra_action(self, pk, **kwargs): assert len(fields) == 2 assert "my_extra_field" in [f.name for f in fields] + def test_viewset_action_with_null_schema(self): + class CustomViewSet(GenericViewSet): + @action(detail=True, schema=None) + def extra_action(self, pk, **kwargs): + pass + + router = SimpleRouter() + router.register(r'detail', CustomViewSet, base_name='detail') + + generator = SchemaGenerator() + view = generator.create_view(router.urls[0].callback, 'GET') + assert view.schema is None + def test_view_with_manual_schema(self): path = '/example'