aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/utils
diff options
context:
space:
mode:
authorTom Christie2013-04-04 21:42:26 +0100
committerTom Christie2013-04-04 21:42:26 +0100
commitf68721ade8d66806296323116ff9a61773ad2be1 (patch)
treed9f44f935ad338f7accb9500383c15bf30bc3621 /rest_framework/utils
parent9e24db022cd8da1a588dd43e6239e07798881c02 (diff)
downloaddjango-rest-framework-f68721ade8d66806296323116ff9a61773ad2be1.tar.bz2
Factor view names/descriptions out of View class
Diffstat (limited to 'rest_framework/utils')
-rw-r--r--rest_framework/utils/breadcrumbs.py5
-rw-r--r--rest_framework/utils/formatting.py77
2 files changed, 80 insertions, 2 deletions
diff --git a/rest_framework/utils/breadcrumbs.py b/rest_framework/utils/breadcrumbs.py
index af21ac79..18b3b207 100644
--- a/rest_framework/utils/breadcrumbs.py
+++ b/rest_framework/utils/breadcrumbs.py
@@ -1,5 +1,6 @@
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):
@@ -16,11 +17,11 @@ def get_breadcrumbs(url):
pass
else:
# Check if this is a REST framework view, and if so add it to the breadcrumbs
- if isinstance(getattr(view, 'cls_instance', None), APIView):
+ if issubclass(getattr(view, 'cls', None), APIView):
# Don't list the same view twice in a row.
# Probably an optional trailing slash.
if not seen or seen[-1] != view:
- breadcrumbs_list.insert(0, (view.cls_instance.get_name(), prefix + url))
+ breadcrumbs_list.insert(0, (get_view_name(view.cls), prefix + url))
seen.append(view)
if url == '':
diff --git a/rest_framework/utils/formatting.py b/rest_framework/utils/formatting.py
new file mode 100644
index 00000000..79566db1
--- /dev/null
+++ b/rest_framework/utils/formatting.py
@@ -0,0 +1,77 @@
+"""
+Utility functions to return a formatted name and description for a given view.
+"""
+from __future__ import unicode_literals
+
+from django.utils.html import escape
+from django.utils.safestring import mark_safe
+from rest_framework.compat import apply_markdown
+import re
+
+
+def _remove_trailing_string(content, trailing):
+ """
+ Strip trailing component `trailing` from `content` if it exists.
+ Used when generating names from view classes.
+ """
+ if content.endswith(trailing) and content != trailing:
+ return content[:-len(trailing)]
+ return content
+
+
+def _remove_leading_indent(content):
+ """
+ Remove leading indent from a block of text.
+ Used when generating descriptions from docstrings.
+ """
+ whitespace_counts = [len(line) - len(line.lstrip(' '))
+ for line in content.splitlines()[1:] if line.lstrip()]
+
+ # unindent the content if needed
+ if whitespace_counts:
+ whitespace_pattern = '^' + (' ' * min(whitespace_counts))
+ content = re.sub(re.compile(whitespace_pattern, re.MULTILINE), '', content)
+ content = content.strip('\n')
+ return content
+
+
+def _camelcase_to_spaces(content):
+ """
+ Translate 'CamelCaseNames' to 'Camel Case Names'.
+ Used when generating names from view classes.
+ """
+ camelcase_boundry = '(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
+ content = re.sub(camelcase_boundry, ' \\1', content).strip()
+ return ' '.join(content.split('_')).title()
+
+
+def get_view_name(cls):
+ """
+ Return a formatted name for an `APIView` class or `@api_view` function.
+ """
+ name = cls.__name__
+ name = _remove_trailing_string(name, 'View')
+ name = _remove_trailing_string(name, 'ViewSet')
+ return _camelcase_to_spaces(name)
+
+
+def get_view_description(cls, html=False):
+ """
+ Return a description for an `APIView` class or `@api_view` function.
+ """
+ description = cls.__doc__ or ''
+ description = _remove_leading_indent(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)