diff --git a/drf_spectacular/contrib/djangorestframework_camel_case.py b/drf_spectacular/contrib/djangorestframework_camel_case.py index fce51cd7..941eb033 100644 --- a/drf_spectacular/contrib/djangorestframework_camel_case.py +++ b/drf_spectacular/contrib/djangorestframework_camel_case.py @@ -1,8 +1,11 @@ import re from typing import Optional +from django.utils.module_loading import import_string + def camelize_serializer_fields(result, generator, request, public): + from django.conf import settings from djangorestframework_camel_case.settings import api_settings from djangorestframework_camel_case.util import camelize_re, underscore_to_camel @@ -11,6 +14,19 @@ def camelize_serializer_fields(result, generator, request, public): # ignore certain field names while camelizing ignore_keys = api_settings.JSON_UNDERSCOREIZE.get("ignore_keys") or () + def has_middleware_installed(): + try: + from djangorestframework_camel_case.middleware import CamelCaseMiddleWare + except ImportError: + return False + + for middleware in [import_string(m) for m in settings.MIDDLEWARE]: + try: + if issubclass(CamelCaseMiddleWare, middleware): + return True + except TypeError: + pass + def camelize_str(key: str) -> str: new_key = re.sub(camelize_re, underscore_to_camel, key) if "_" in key else key if key in ignore_keys or new_key in ignore_keys: @@ -36,10 +52,11 @@ def camelize_component(schema: dict, name: Optional[str] = None) -> dict: if component_type == 'schemas': camelize_component(component.schema) - for url_schema in result["paths"].values(): - for method_schema in url_schema.values(): - for parameter in method_schema.get("parameters", []): - parameter["name"] = camelize_str(parameter["name"]) + if has_middleware_installed(): + for url_schema in result["paths"].values(): + for method_schema in url_schema.values(): + for parameter in method_schema.get("parameters", []): + parameter["name"] = camelize_str(parameter["name"]) # inplace modification of components also affect result dict, so regeneration is not necessary return result diff --git a/tests/contrib/test_djangorestframework_camel_case.py b/tests/contrib/test_djangorestframework_camel_case.py index 108b2ec5..48ba6724 100644 --- a/tests/contrib/test_djangorestframework_camel_case.py +++ b/tests/contrib/test_djangorestframework_camel_case.py @@ -14,7 +14,7 @@ from typing_extensions import TypedDict from drf_spectacular.contrib.djangorestframework_camel_case import camelize_serializer_fields -from drf_spectacular.utils import extend_schema, OpenApiParameter +from drf_spectacular.utils import OpenApiParameter, extend_schema from tests import assert_schema, generate_schema @@ -49,8 +49,8 @@ def get_field_nested_ignored(self) -> NestedObject: # type: ignore @extend_schema( parameters=[ OpenApiParameter( - name="field_one", - description="filter_field", + name="field_parameter", + description="filter_parameter", required=False, type=str, ), @@ -78,8 +78,34 @@ def home(self, request): } ) @pytest.mark.contrib('djangorestframework_camel_case') -def test_camelize_serializer_fields(): +def test_camelize_serializer_fields(no_warnings): assert_schema( generate_schema('a_b_c', FakeViewset), 'tests/contrib/test_djangorestframework_camel_case.yml' ) + + +@mock.patch( + 'django.conf.settings.MIDDLEWARE', + ['djangorestframework_camel_case.middleware.CamelCaseMiddleWare'], + create=True +) +@mock.patch( + 'drf_spectacular.settings.spectacular_settings.POSTPROCESSING_HOOKS', + [camelize_serializer_fields] +) +@mock.patch( + 'djangorestframework_camel_case.settings.api_settings.JSON_UNDERSCOREIZE', + { + 'no_underscore_before_number': False, + 'ignore_fields': ('field_nested_ignored',), + 'ignore_keys': ('field_ignored',), + } +) +@pytest.mark.contrib('djangorestframework_camel_case') +def test_camelize_middleware(no_warnings): + assert_schema( + generate_schema('a_b_c', FakeViewset), + 'tests/contrib/test_djangorestframework_camel_case.yml', + reverse_transforms=[lambda x: x.replace("field_parameter", "fieldParameter")] + ) diff --git a/tests/contrib/test_djangorestframework_camel_case.yml b/tests/contrib/test_djangorestframework_camel_case.yml index 7d519fcd..aba844b0 100644 --- a/tests/contrib/test_djangorestframework_camel_case.yml +++ b/tests/contrib/test_djangorestframework_camel_case.yml @@ -8,10 +8,10 @@ paths: operationId: a_b_c_list parameters: - in: query - name: fieldOne + name: field_parameter schema: type: string - description: filter_field + description: filter_parameter tags: - a_b_c security: @@ -32,10 +32,10 @@ paths: operationId: a_b_c_home_retrieve parameters: - in: query - name: fieldOne + name: field_parameter schema: type: string - description: filter_field + description: filter_parameter tags: - a_b_c security: