diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index c5ea89fa..489e48ad 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import permissions, renderers, serializers from rest_framework.fields import _UnvalidatedField, empty -from rest_framework.generics import GenericAPIView +from rest_framework.generics import CreateAPIView, GenericAPIView, ListCreateAPIView from rest_framework.mixins import ListModelMixin from rest_framework.schemas.inspectors import ViewInspector from rest_framework.schemas.utils import get_pk_description # type: ignore @@ -27,9 +27,9 @@ ComponentRegistry, ResolvedComponent, UnableToProceedError, append_meta, build_array_type, build_basic_type, build_choice_field, build_examples_list, build_media_type_object, build_object_type, build_parameter_type, error, follow_field_source, force_instance, get_doc, - get_view_model, is_basic_type, is_create_operation, is_field, is_list_serializer, - is_patched_serializer, is_serializer, is_trivial_string_variation, resolve_regex_path_parameter, - resolve_type_hint, safe_ref, warn, + get_view_model, is_basic_type, is_field, is_list_serializer, is_patched_serializer, + is_serializer, is_trivial_string_variation, resolve_regex_path_parameter, resolve_type_hint, + safe_ref, warn, ) from drf_spectacular.settings import spectacular_settings from drf_spectacular.types import OpenApiTypes, build_generic_type @@ -118,6 +118,15 @@ def _is_list_view(self, serializer=None): return False + def _is_create_operation(self): + if self.method != 'POST': + return False + if getattr(self.view, 'action', None) == 'create': + return True + if isinstance(self.view, (ListCreateAPIView, CreateAPIView)): + return True + return False + def get_override_parameters(self): """ override this for custom behaviour """ return [] @@ -999,7 +1008,7 @@ def _get_response_bodies(self): ): if self.method == 'DELETE': return {'204': {'description': _('No response body')}} - if is_create_operation(self.method, self.view): + if self._is_create_operation(): return {'201': self._get_response_for_code(response_serializers, '201')} return {'200': self._get_response_for_code(response_serializers, '200')} elif isinstance(response_serializers, dict): diff --git a/drf_spectacular/plumbing.py b/drf_spectacular/plumbing.py index 2c8eb404..e9f6fc7d 100644 --- a/drf_spectacular/plumbing.py +++ b/drf_spectacular/plumbing.py @@ -26,7 +26,7 @@ ) from django.utils.functional import Promise, cached_property from django.utils.module_loading import import_string -from rest_framework import exceptions, fields, generics, mixins, serializers, versioning +from rest_framework import exceptions, fields, mixins, serializers, versioning from rest_framework.settings import api_settings from rest_framework.test import APIRequestFactory from rest_framework.utils.mediatypes import _MediaType @@ -106,16 +106,6 @@ def is_trivial_string_variation(a: str, b: str): return a == b -def is_create_operation(method, view): - if method != 'POST': - return False - if getattr(view, 'action', None) == 'create': - return True - if isinstance(view, (generics.ListCreateAPIView, generics.CreateAPIView)): - return True - return False - - def get_lib_doc_excludes(): # do not import on package level due to potential import recursion when loading # extensions as recommended: USER's settings.py -> USER EXTENSIONS -> extensions.py diff --git a/tox.ini b/tox.ini index 88815393..47ec6c57 100644 --- a/tox.ini +++ b/tox.ini @@ -51,6 +51,7 @@ exclude_lines = except ImportError raise NotImplementedError if __name__ == .__main__.: + if TYPE_CHECKING: [flake8] ignore =