diff --git a/rest_framework/schemas/openapi.py b/rest_framework/schemas/openapi.py index 5860bf413..2fe251df0 100644 --- a/rest_framework/schemas/openapi.py +++ b/rest_framework/schemas/openapi.py @@ -5,11 +5,11 @@ from django.utils.encoding import force_text from rest_framework import exceptions, serializers from rest_framework.compat import uritemplate - from .generators import BaseSchemaGenerator from .inspectors import ViewInspector from .utils import get_pk_description, is_list_view + # Generator @@ -100,12 +100,17 @@ class AutoSchema(ViewInspector): """ Compute an operation ID from the model, serializer or view name. """ + # TODO: Allow an attribute/method on the view to change that ID? # Avoid cyclic imports from rest_framework.generics import GenericAPIView + method_name = getattr(self.view, 'action', method.lower()) + if is_list_view(path, method, self.view): action = 'List' + elif method_name not in self.method_mapping: + action = method_name else: action = self.method_mapping[method.lower()] diff --git a/tests/schemas/test_openapi.py b/tests/schemas/test_openapi.py index 4c64810f7..cf90a109e 100644 --- a/tests/schemas/test_openapi.py +++ b/tests/schemas/test_openapi.py @@ -2,11 +2,10 @@ import pytest from django.conf.urls import url from django.test import RequestFactory, TestCase, override_settings -from rest_framework import filters, generics, pagination, serializers +from rest_framework import filters, generics, pagination, routers, serializers from rest_framework.compat import uritemplate from rest_framework.request import Request from rest_framework.schemas.openapi import AutoSchema, SchemaGenerator - from . import views @@ -130,6 +129,21 @@ class TestOperationIntrospection(TestCase): assert responses['200']['content']['application/json']['schema']['required'] == ['text'] assert list(responses['200']['content']['application/json']['schema']['properties'].keys()) == ['text'] + def test_repeat_operation_ids(self): + router = routers.SimpleRouter() + router.register('account', views.ExampleGenericViewSet, basename="account") + urlpatterns = router.urls + + generator = SchemaGenerator(patterns=urlpatterns) + + request = create_request('/') + schema = generator.get_schema(request=request) + schema_str = str(schema) + print(schema_str) + assert schema_str.count("operationId") == 2 + assert schema_str.count("newExample") == 1 + assert schema_str.count("oldExample") == 1 + @pytest.mark.skipif(uritemplate is None, reason='uritemplate not installed.') @override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema'}) diff --git a/tests/schemas/views.py b/tests/schemas/views.py index cf054b885..f8fd5e517 100644 --- a/tests/schemas/views.py +++ b/tests/schemas/views.py @@ -1,4 +1,5 @@ from rest_framework import permissions, serializers +from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet @@ -34,3 +35,11 @@ class ExampleGenericViewSet(GenericViewSet): serializer = self.get_serializer(data=now.date(), datetime=now) return Response(serializer.data) + + @action(detail=False) + def new(self, *args, **kwargs): + pass + + @action(detail=False) + def old(self, *args, **kwargs): + pass