Skip to content

Commit

Permalink
Merge pull request #1026 from tfranzel/fix_exclude
Browse files Browse the repository at this point in the history
bugfix exclude behavior on subclassing #1025
  • Loading branch information
tfranzel committed Jul 11, 2023
2 parents d4d16ac + f004304 commit fa568ce
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
7 changes: 7 additions & 0 deletions drf_spectacular/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ def get_operation(self, path, path_regex, path_prefix, method, registry: Compone
self.path_prefix = path_prefix
self.method = method.upper()

if self.is_excluded():
return None

operation = {'operationId': self.get_operation_id()}

description = self.get_description()
Expand Down Expand Up @@ -104,6 +107,10 @@ def get_operation(self, path, path_regex, path_prefix, method, registry: Compone

return operation

def is_excluded(self):
""" override this for custom behaviour """
return False

def _is_list_view(self, serializer=None):
"""
partially heuristic approach to determine if a view yields an object or a
Expand Down
9 changes: 6 additions & 3 deletions drf_spectacular/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ def extend_schema(
deprecated: Optional[bool] = None,
tags: Optional[Sequence[str]] = None,
filters: Optional[bool] = None,
exclude: bool = False,
exclude: Optional[bool] = None,
operation: Optional[Dict] = None,
methods: Optional[Sequence[str]] = None,
versions: Optional[Sequence[str]] = None,
Expand Down Expand Up @@ -417,12 +417,15 @@ class ExtendedSchema(BaseSchema):
def get_operation(self, path, path_regex, path_prefix, method, registry):
self.method = method.upper()

if exclude and is_in_scope(self):
return None
if operation is not None and is_in_scope(self):
return operation
return super().get_operation(path, path_regex, path_prefix, method, registry)

def is_excluded(self):
if exclude is not None and is_in_scope(self):
return exclude
return super().is_excluded()

def get_operation_id(self):
if operation_id and is_in_scope(self):
return operation_id
Expand Down
24 changes: 24 additions & 0 deletions tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3159,3 +3159,27 @@ def view_func(request, format=None):
'encoding': {'field': {'style': 'form', 'explode': True}}
}
}


def test_exclude_then_include_subclassed_view(no_warnings):
@extend_schema(exclude=True)
class X1ViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = SimpleSerializer
queryset = SimpleModel.objects.none()

@extend_schema(exclude=False)
class X2ViewSet(X1ViewSet):
pass

class X3ViewSet(X2ViewSet):
pass

router = routers.SimpleRouter()
router.register('x1', X1ViewSet)
router.register('x2', X2ViewSet)
router.register('x3', X3ViewSet)

schema = generate_schema(None, patterns=router.urls)
assert '/x1/' not in schema['paths']
assert '/x2/' in schema['paths']
assert '/x3/' in schema['paths']

0 comments on commit fa568ce

Please sign in to comment.