mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-27 03:54:01 +03:00
Merge branch 'master' of https://github.com/tomchristie/django-rest-framework
This commit is contained in:
commit
e0dddbc5de
|
@ -15,7 +15,9 @@ For example, you might have a `urls.py` that looks something like this:
|
|||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import itertools
|
||||
from collections import namedtuple
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from rest_framework import views
|
||||
from rest_framework.compat import patterns, url
|
||||
from rest_framework.response import Response
|
||||
|
@ -38,6 +40,13 @@ def replace_methodname(format_string, methodname):
|
|||
return ret
|
||||
|
||||
|
||||
def flatten(list_of_lists):
|
||||
"""
|
||||
Takes an iterable of iterables, returns a single iterable containing all items
|
||||
"""
|
||||
return itertools.chain(*list_of_lists)
|
||||
|
||||
|
||||
class BaseRouter(object):
|
||||
def __init__(self):
|
||||
self.registry = []
|
||||
|
@ -130,12 +139,17 @@ class SimpleRouter(BaseRouter):
|
|||
Returns a list of the Route namedtuple.
|
||||
"""
|
||||
|
||||
known_actions = flatten([route.mapping.values() for route in self.routes])
|
||||
|
||||
# Determine any `@action` or `@link` decorated methods on the viewset
|
||||
dynamic_routes = []
|
||||
for methodname in dir(viewset):
|
||||
attr = getattr(viewset, methodname)
|
||||
httpmethods = getattr(attr, 'bind_to_methods', None)
|
||||
if httpmethods:
|
||||
if methodname in known_actions:
|
||||
raise ImproperlyConfigured('Cannot use @action or @link decorator on '
|
||||
'method "%s" as it is an existing route' % methodname)
|
||||
httpmethods = [method.lower() for method in httpmethods]
|
||||
dynamic_routes.append((httpmethods, methodname))
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||
from django.db import models
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from rest_framework import serializers, viewsets, permissions
|
||||
from rest_framework.compat import include, patterns, url
|
||||
from rest_framework.decorators import link, action
|
||||
|
@ -191,3 +192,24 @@ class TestActionKeywordArgs(TestCase):
|
|||
response.data,
|
||||
{'permission_classes': [permissions.AllowAny]}
|
||||
)
|
||||
|
||||
class TestActionAppliedToExistingRoute(TestCase):
|
||||
"""
|
||||
Ensure `@action` decorator raises an except when applied
|
||||
to an existing route
|
||||
"""
|
||||
|
||||
def test_exception_raised_when_action_applied_to_existing_route(self):
|
||||
class TestViewSet(viewsets.ModelViewSet):
|
||||
|
||||
@action()
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return Response({
|
||||
'hello': 'world'
|
||||
})
|
||||
|
||||
self.router = SimpleRouter()
|
||||
self.router.register(r'test', TestViewSet, base_name='test')
|
||||
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
self.router.urls
|
||||
|
|
Loading…
Reference in New Issue
Block a user