Add 'ViewSet.get_extra_actions()'

This commit is contained in:
Ryan P Kilby 2017-12-22 02:12:40 -05:00
parent e090ba2dd9
commit 72b73790dd
2 changed files with 23 additions and 2 deletions

View File

@ -19,6 +19,7 @@ automatically.
from __future__ import unicode_literals
from functools import update_wrapper
from inspect import getmembers
from django.utils.decorators import classonlymethod
from django.views.decorators.csrf import csrf_exempt
@ -27,6 +28,10 @@ from rest_framework import generics, mixins, views
from rest_framework.reverse import reverse
def _is_extra_action(attr):
return hasattr(attr, 'bind_to_methods')
class ViewSetMixin(object):
"""
This is the magic.
@ -112,8 +117,7 @@ class ViewSetMixin(object):
def initialize_request(self, request, *args, **kwargs):
"""
Set the `.action` attribute on the view,
depending on the request method.
Set the `.action` attribute on the view, depending on the request method.
"""
request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs)
method = request.method.lower()
@ -135,6 +139,13 @@ class ViewSetMixin(object):
return reverse(url_name, *args, **kwargs)
@classmethod
def get_extra_actions(cls):
"""
Get the methods that are marked as an extra ViewSet `@action`.
"""
return [method for _, method in getmembers(cls, _is_extra_action)]
class ViewSet(ViewSetMixin, views.APIView):
"""

View File

@ -111,6 +111,16 @@ class InitializeViewSetsTestCase(TestCase):
self.assertIn(attribute, dir(view))
class GetExtraActionTests(TestCase):
def test_extra_actions(self):
view = ActionViewSet()
actual = [action.__name__ for action in view.get_extra_actions()]
expected = ['custom_detail_action', 'custom_list_action', 'detail_action', 'list_action']
self.assertEqual(actual, expected)
@override_settings(ROOT_URLCONF='tests.test_viewsets')
class ReverseActionTests(TestCase):
def test_default_basename(self):