mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 00:19:53 +03:00
Ensure that viewset actions may be identified as list views
is_list_view only checks to see whether the view action is 'list'. This means you cannot define an action with `detail=False` that will generate a schema with a list response. This commit allows specifying 'many=True' on an action to achieve this
This commit is contained in:
parent
070c32f4a6
commit
ae5ba11e39
|
@ -15,7 +15,7 @@ def is_list_view(path, method, view):
|
||||||
"""
|
"""
|
||||||
if hasattr(view, 'action'):
|
if hasattr(view, 'action'):
|
||||||
# Viewsets have an explicitly defined action, which we can inspect.
|
# Viewsets have an explicitly defined action, which we can inspect.
|
||||||
return view.action == 'list'
|
return view.action == 'list' or view.many
|
||||||
|
|
||||||
if method.lower() != 'get':
|
if method.lower() != 'get':
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -75,6 +75,9 @@ class ViewSetMixin:
|
||||||
# The detail initkwarg is reserved for introspecting the viewset type.
|
# The detail initkwarg is reserved for introspecting the viewset type.
|
||||||
cls.detail = None
|
cls.detail = None
|
||||||
|
|
||||||
|
# The many initkwarg is reserved for introspecting the viewset return type.
|
||||||
|
cls.many = None
|
||||||
|
|
||||||
# Setting a basename allows a view to reverse its action urls. This
|
# Setting a basename allows a view to reverse its action urls. This
|
||||||
# value is provided by the router through the initkwargs.
|
# value is provided by the router through the initkwargs.
|
||||||
cls.basename = None
|
cls.basename = None
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import filters, generics, pagination, routers, serializers
|
from rest_framework import filters, generics, pagination, routers, serializers
|
||||||
from rest_framework.authtoken.views import obtain_auth_token
|
from rest_framework.authtoken.views import obtain_auth_token
|
||||||
from rest_framework.compat import uritemplate
|
from rest_framework.compat import uritemplate
|
||||||
|
from rest_framework.decorators import action
|
||||||
from rest_framework.parsers import JSONParser, MultiPartParser
|
from rest_framework.parsers import JSONParser, MultiPartParser
|
||||||
from rest_framework.renderers import (
|
from rest_framework.renderers import (
|
||||||
BaseRenderer, BrowsableAPIRenderer, JSONOpenAPIRenderer, JSONRenderer,
|
BaseRenderer, BrowsableAPIRenderer, JSONOpenAPIRenderer, JSONRenderer,
|
||||||
|
@ -866,6 +867,22 @@ class TestOperationIntrospection(TestCase):
|
||||||
assert schema['paths']['/account/{id}/']['patch']['operationId'] == 'partialUpdateExampleViewSet'
|
assert schema['paths']['/account/{id}/']['patch']['operationId'] == 'partialUpdateExampleViewSet'
|
||||||
assert schema['paths']['/account/{id}/']['delete']['operationId'] == 'destroyExampleViewSet'
|
assert schema['paths']['/account/{id}/']['delete']['operationId'] == 'destroyExampleViewSet'
|
||||||
|
|
||||||
|
def test_viewset_with_list_action(self):
|
||||||
|
router = routers.SimpleRouter()
|
||||||
|
|
||||||
|
class ViewSetWithAction(views.ExampleViewSet):
|
||||||
|
@action(detail=False, many=True)
|
||||||
|
def list_action(self, request, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
router.register('account', ViewSetWithAction, basename="account")
|
||||||
|
urlpatterns = router.urls
|
||||||
|
|
||||||
|
generator = SchemaGenerator(patterns=urlpatterns)
|
||||||
|
request = create_request('/')
|
||||||
|
schema = generator.get_schema(request=request)
|
||||||
|
assert schema['paths']['/account/list_action/']['get']['responses']['200']['content']['application/json']['schema']['type'] == 'array'
|
||||||
|
|
||||||
def test_serializer_datefield(self):
|
def test_serializer_datefield(self):
|
||||||
path = '/'
|
path = '/'
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user