Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix when multiple actions have the same url_path #800

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/drf_yasg/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,14 @@ def get_api_endpoints(self, patterns=None, prefix='', app_name=None, namespace=N
if self.should_include_endpoint(path, callback, app_name or '', namespace or '', url_name):
path = self.replace_version(path, callback)

# avoid adding endpoints that have already been seen,
# as Django resolves urls in top-down order
if path in ignored_endpoints:
continue
ignored_endpoints.add(path)

for method in self.get_allowed_methods(callback):
# avoid adding endpoints that have already been seen,
# as Django resolves urls in top-down order
ignore_endpoint = (path, method)
if ignore_endpoint in ignored_endpoints:
continue
ignored_endpoints.add(ignore_endpoint)

endpoint = (path, method, callback)
api_endpoints.append(endpoint)
except Exception: # pragma: no cover
Expand Down
35 changes: 35 additions & 0 deletions tests/test_schema_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,41 @@ def action_post(self, request):
assert action_ops['delete']['description'] == 'mapping docstring get/delete'


@pytest.mark.skipif(not MethodMapper or not action, reason="actions - same url_path ")
def test_action_same_url_path():
class ActionViewSet(viewsets.ViewSet):
@swagger_auto_schema(method='get', operation_id='method_get')
@action(detail=False, methods=['get'], url_path='test')
def action_get(self, request):
"""docstring get"""
pass

@swagger_auto_schema(method='post', operation_id='method_post')
@action(detail=False, methods=['post'], url_path='test')
def action_post(self, request):
"""docstring post"""
pass

router = routers.DefaultRouter()
router.register(r'action', ActionViewSet, **_basename_or_base_name('action'))

generator = OpenAPISchemaGenerator(
info=openapi.Info(title="Test generator", default_version="v1"),
version="v2",
url='',
patterns=router.urls
)

for _ in range(3):
swagger = generator.get_schema(None, True)
action_ops = swagger['paths']['/test/']
methods = ['get', 'post']
assert all(mth in action_ops for mth in methods)
assert all(action_ops[mth]['operationId'] == 'method_' + mth for mth in methods)
assert action_ops['post']['description'] == 'docstring post'
assert action_ops['get']['description'] == 'docstring get'


@pytest.mark.parametrize('choices, expected_type', [
(['A', 'B'], openapi.TYPE_STRING),
([u'A', u'B'], openapi.TYPE_STRING),
Expand Down