OpenAPI:Operations must have unique operationIds.

This commit is contained in:
dongfangtianyu 2019-04-07 00:31:17 +08:00
parent 570da685b5
commit 7a6d5d4033
3 changed files with 31 additions and 3 deletions

View File

@ -5,11 +5,11 @@ from django.utils.encoding import force_text
from rest_framework import exceptions, serializers from rest_framework import exceptions, serializers
from rest_framework.compat import uritemplate from rest_framework.compat import uritemplate
from .generators import BaseSchemaGenerator from .generators import BaseSchemaGenerator
from .inspectors import ViewInspector from .inspectors import ViewInspector
from .utils import get_pk_description, is_list_view from .utils import get_pk_description, is_list_view
# Generator # Generator
@ -100,12 +100,17 @@ class AutoSchema(ViewInspector):
""" """
Compute an operation ID from the model, serializer or view name. Compute an operation ID from the model, serializer or view name.
""" """
# TODO: Allow an attribute/method on the view to change that ID? # TODO: Allow an attribute/method on the view to change that ID?
# Avoid cyclic imports # Avoid cyclic imports
from rest_framework.generics import GenericAPIView from rest_framework.generics import GenericAPIView
method_name = getattr(self.view, 'action', method.lower())
if is_list_view(path, method, self.view): if is_list_view(path, method, self.view):
action = 'List' action = 'List'
elif method_name not in self.method_mapping:
action = method_name
else: else:
action = self.method_mapping[method.lower()] action = self.method_mapping[method.lower()]

View File

@ -2,11 +2,10 @@ import pytest
from django.conf.urls import url from django.conf.urls import url
from django.test import RequestFactory, TestCase, override_settings 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.compat import uritemplate
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.schemas.openapi import AutoSchema, SchemaGenerator from rest_framework.schemas.openapi import AutoSchema, SchemaGenerator
from . import views from . import views
@ -130,6 +129,21 @@ class TestOperationIntrospection(TestCase):
assert responses['200']['content']['application/json']['schema']['required'] == ['text'] assert responses['200']['content']['application/json']['schema']['required'] == ['text']
assert list(responses['200']['content']['application/json']['schema']['properties'].keys()) == ['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.') @pytest.mark.skipif(uritemplate is None, reason='uritemplate not installed.')
@override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema'}) @override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema'})

View File

@ -1,4 +1,5 @@
from rest_framework import permissions, serializers from rest_framework import permissions, serializers
from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
@ -34,3 +35,11 @@ class ExampleGenericViewSet(GenericViewSet):
serializer = self.get_serializer(data=now.date(), datetime=now) serializer = self.get_serializer(data=now.date(), datetime=now)
return Response(serializer.data) return Response(serializer.data)
@action(detail=False)
def new(self, *args, **kwargs):
pass
@action(detail=False)
def old(self, *args, **kwargs):
pass