aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/renderers.py5
-rw-r--r--rest_framework/settings.py6
-rw-r--r--rest_framework/tests/test_description.py9
-rw-r--r--rest_framework/utils/breadcrumbs.py5
-rw-r--r--rest_framework/utils/formatting.py38
-rw-r--r--rest_framework/views.py27
6 files changed, 50 insertions, 40 deletions
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index 3a03ca33..1006e26c 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -24,7 +24,6 @@ from rest_framework.settings import api_settings
from rest_framework.request import clone_request
from rest_framework.utils import encoders
from rest_framework.utils.breadcrumbs import get_breadcrumbs
-from rest_framework.utils.formatting import get_view_name, get_view_description
from rest_framework import exceptions, parsers, status, VERSION
@@ -498,10 +497,10 @@ class BrowsableAPIRenderer(BaseRenderer):
return GenericContentForm()
def get_name(self, view):
- return get_view_name(view.__class__, getattr(view, 'suffix', None))
+ return view.get_view_name()
def get_description(self, view):
- return get_view_description(view.__class__, html=True)
+ return view.get_view_description(html=True)
def get_breadcrumbs(self, request):
return get_breadcrumbs(request.path)
diff --git a/rest_framework/settings.py b/rest_framework/settings.py
index 8fd177d5..0b2bdb62 100644
--- a/rest_framework/settings.py
+++ b/rest_framework/settings.py
@@ -69,6 +69,10 @@ DEFAULTS = {
'PAGINATE_BY': None,
'PAGINATE_BY_PARAM': None,
+ # View configuration
+ 'VIEW_NAME_FUNCTION': 'rest_framework.utils.formatting.view_name',
+ 'VIEW_DESCRIPTION_FUNCTION': 'rest_framework.utils.formatting.view_description',
+
# Authentication
'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
'UNAUTHENTICATED_TOKEN': None,
@@ -125,6 +129,8 @@ IMPORT_STRINGS = (
'TEST_REQUEST_RENDERER_CLASSES',
'UNAUTHENTICATED_USER',
'UNAUTHENTICATED_TOKEN',
+ 'VIEW_NAME_FUNCTION',
+ 'VIEW_DESCRIPTION_FUNCTION'
)
diff --git a/rest_framework/tests/test_description.py b/rest_framework/tests/test_description.py
index 8019f5ec..4c03c1de 100644
--- a/rest_framework/tests/test_description.py
+++ b/rest_framework/tests/test_description.py
@@ -6,7 +6,6 @@ from rest_framework.compat import apply_markdown, smart_text
from rest_framework.views import APIView
from rest_framework.tests.description import ViewWithNonASCIICharactersInDocstring
from rest_framework.tests.description import UTF8_TEST_DOCSTRING
-from rest_framework.utils.formatting import get_view_name, get_view_description
# We check that docstrings get nicely un-indented.
DESCRIPTION = """an example docstring
@@ -58,7 +57,7 @@ class TestViewNamesAndDescriptions(TestCase):
"""
class MockView(APIView):
pass
- self.assertEqual(get_view_name(MockView), 'Mock')
+ self.assertEqual(MockView().get_view_name(), 'Mock')
def test_view_description_uses_docstring(self):
"""Ensure view descriptions are based on the docstring."""
@@ -78,7 +77,7 @@ class TestViewNamesAndDescriptions(TestCase):
# hash style header #"""
- self.assertEqual(get_view_description(MockView), DESCRIPTION)
+ self.assertEqual(MockView().get_view_description(), DESCRIPTION)
def test_view_description_supports_unicode(self):
"""
@@ -86,7 +85,7 @@ class TestViewNamesAndDescriptions(TestCase):
"""
self.assertEqual(
- get_view_description(ViewWithNonASCIICharactersInDocstring),
+ ViewWithNonASCIICharactersInDocstring().get_view_description(),
smart_text(UTF8_TEST_DOCSTRING)
)
@@ -97,7 +96,7 @@ class TestViewNamesAndDescriptions(TestCase):
"""
class MockView(APIView):
pass
- self.assertEqual(get_view_description(MockView), '')
+ self.assertEqual(MockView().get_view_description(), '')
def test_markdown(self):
"""
diff --git a/rest_framework/utils/breadcrumbs.py b/rest_framework/utils/breadcrumbs.py
index d51374b0..0384faba 100644
--- a/rest_framework/utils/breadcrumbs.py
+++ b/rest_framework/utils/breadcrumbs.py
@@ -1,6 +1,5 @@
from __future__ import unicode_literals
from django.core.urlresolvers import resolve, get_script_prefix
-from rest_framework.utils.formatting import get_view_name
def get_breadcrumbs(url):
@@ -29,8 +28,8 @@ def get_breadcrumbs(url):
# Don't list the same view twice in a row.
# Probably an optional trailing slash.
if not seen or seen[-1] != view:
- suffix = getattr(view, 'suffix', None)
- name = get_view_name(view.cls, suffix)
+ instance = view.cls()
+ name = instance.get_view_name()
breadcrumbs_list.insert(0, (name, prefix + url))
seen.append(view)
diff --git a/rest_framework/utils/formatting.py b/rest_framework/utils/formatting.py
index 4bec8387..89a89252 100644
--- a/rest_framework/utils/formatting.py
+++ b/rest_framework/utils/formatting.py
@@ -7,6 +7,7 @@ from django.utils.html import escape
from django.utils.safestring import mark_safe
from rest_framework.compat import apply_markdown, smart_text
import re
+from rest_framework.settings import api_settings
def _remove_trailing_string(content, trailing):
@@ -44,37 +45,30 @@ def _camelcase_to_spaces(content):
content = re.sub(camelcase_boundry, ' \\1', content).strip()
return ' '.join(content.split('_')).title()
-
-def get_view_name(cls, suffix=None):
+def markup_description(description):
"""
- Return a formatted name for an `APIView` class or `@api_view` function.
+ Apply HTML markup to the given description.
"""
- name = cls.__name__
+ if apply_markdown:
+ description = apply_markdown(description)
+ else:
+ description = escape(description).replace('\n', '<br />')
+ return mark_safe(description)
+
+
+def view_name(instance, view, suffix=None):
+ name = view.__name__
name = _remove_trailing_string(name, 'View')
name = _remove_trailing_string(name, 'ViewSet')
name = _camelcase_to_spaces(name)
if suffix:
name += ' ' + suffix
- return name
+ return name
-def get_view_description(cls, html=False):
- """
- Return a description for an `APIView` class or `@api_view` function.
- """
- description = cls.__doc__ or ''
+def view_description(instance, view, html=False):
+ description = view.__doc__ or ''
description = _remove_leading_indent(smart_text(description))
if html:
return markup_description(description)
- return description
-
-
-def markup_description(description):
- """
- Apply HTML markup to the given description.
- """
- if apply_markdown:
- description = apply_markdown(description)
- else:
- description = escape(description).replace('\n', '<br />')
- return mark_safe(description)
+ return description \ No newline at end of file
diff --git a/rest_framework/views.py b/rest_framework/views.py
index d51233a9..4553714a 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -12,7 +12,6 @@ from rest_framework.compat import View, HttpResponseBase
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.settings import api_settings
-from rest_framework.utils.formatting import get_view_name, get_view_description
class APIView(View):
@@ -25,6 +24,9 @@ class APIView(View):
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
+ view_name_function = api_settings.VIEW_NAME_FUNCTION
+ view_description_function = api_settings.VIEW_DESCRIPTION_FUNCTION
+
@classmethod
def as_view(cls, **initkwargs):
"""
@@ -157,6 +159,21 @@ class APIView(View):
self._negotiator = self.content_negotiation_class()
return self._negotiator
+ def get_view_name(self):
+ """
+ Get the view name
+ """
+ # This is used by ViewSets to disambiguate instance vs list views
+ view_name_suffix = getattr(self, 'suffix', None)
+
+ return self.view_name_function(self.__class__, view_name_suffix)
+
+ def get_view_description(self, html=False):
+ """
+ Get the view description
+ """
+ return self.view_description_function(self.__class__, html)
+
# API policy implementation methods
def perform_content_negotiation(self, request, force=False):
@@ -342,16 +359,12 @@ class APIView(View):
Return a dictionary of metadata about the view.
Used to return responses for OPTIONS requests.
"""
-
- # This is used by ViewSets to disambiguate instance vs list views
- view_name_suffix = getattr(self, 'suffix', None)
-
# By default we can't provide any form-like information, however the
# generic views override this implementation and add additional
# information for POST and PUT methods, based on the serializer.
ret = SortedDict()
- ret['name'] = get_view_name(self.__class__, view_name_suffix)
- ret['description'] = get_view_description(self.__class__)
+ ret['name'] = self.get_view_name()
+ ret['description'] = self.get_view_description()
ret['renders'] = [renderer.media_type for renderer in self.renderer_classes]
ret['parses'] = [parser.media_type for parser in self.parser_classes]
return ret