diff --git a/drfdocs/api_docs.py b/drfdocs/api_docs.py index 809f214..93bc46a 100644 --- a/drfdocs/api_docs.py +++ b/drfdocs/api_docs.py @@ -1,22 +1,31 @@ from django.conf import settings from django.core.urlresolvers import RegexURLResolver, RegexURLPattern +from drfdocs.api_endpoint import ApiEndpoint +from rest_framework.views import APIView class ApiDocumentation(object): excluded_apps = ["admin", "drfdocs"] excluded_endpoints = ["serve"] - root_urlconf = __import__(settings.ROOT_URLCONF) def __init__(self): - self.view_names = [] - self.get_all_view_names(self.root_urlconf.urls.urlpatterns) + self.endpoints = [] + root_urlconf = __import__(settings.ROOT_URLCONF) + self.get_all_view_names(root_urlconf.urls.urlpatterns) - def get_all_view_names(self, urlpatterns): + def get_all_view_names(self, urlpatterns, parent_pattern=None): for pattern in urlpatterns: if isinstance(pattern, RegexURLResolver) and (pattern.app_name not in self.excluded_apps): - self.get_all_view_names(pattern.url_patterns) - elif isinstance(pattern, RegexURLPattern) and (pattern.callback.__name__ not in self.excluded_endpoints): - self.view_names.append(pattern.callback.__name__) + self.get_all_view_names(urlpatterns=pattern.url_patterns, parent_pattern=pattern) + elif isinstance(pattern, RegexURLPattern) and (pattern.callback.__name__ not in self.excluded_endpoints) and self._is_drf_view(pattern): + api_endpoint = ApiEndpoint(pattern, parent_pattern) + self.endpoints.append(api_endpoint) - def get_views(self): - return self.view_names + def _is_drf_view(self, pattern): + # Should check whether a pattern inherits from DRF's APIView + if (hasattr(pattern.callback, 'cls') and issubclass(pattern.callback.cls, APIView)): + return True + return False + + def get_endpoints(self): + return self.endpoints diff --git a/drfdocs/api_endpoint.py b/drfdocs/api_endpoint.py index e69de29..e0a57ef 100644 --- a/drfdocs/api_endpoint.py +++ b/drfdocs/api_endpoint.py @@ -0,0 +1,16 @@ +from django.contrib.admindocs.views import simplify_regex + + +class ApiEndpoint(object): + + def __init__(self, pattern, parent_pattern=None): + self.pattern = pattern + self.name = pattern.name + self.path = self._get_path(parent_pattern) + self.view_name = pattern.callback.__name__ + + def _get_path(self, parent_pattern): + if parent_pattern: + parent_path = simplify_regex(parent_pattern.regex.pattern)[:-1] + return "{0}{1}".format(parent_path, simplify_regex(self.pattern.regex.pattern)) + return simplify_regex(self.pattern.regex.pattern) diff --git a/drfdocs/static/css/style.css b/drfdocs/static/css/style.css new file mode 100644 index 0000000..c53d20d --- /dev/null +++ b/drfdocs/static/css/style.css @@ -0,0 +1,92 @@ +/* @group Misc */ + +body { + background-color: #FEFEFE; +} + +.jumbotron { + margin: 50px 0 40px; + text-align: center; +} + +/* @end Misc */ + + +/* @group Endpoint */ + +.endpoint { + padding: 5px 20px; + margin: 20px 0; + background-color: #ecf0f1; +} + +.endpoint .title { + font-family: Menlo,Monaco,Consolas,"Courier New",monospace; +} + +/* @end Endpoint */ + + +/* @group Footer */ + +.footer { + text-align: center; + padding: 20px; + margin-bottom: 20px; +} + +.footer .links { + padding: 20px 0; +} + +.footer .links .fa { + margin: 0 10px; + font-size: 22px; +} + +/* @end Footer */ + + +/* @group Github Ribbon - SVG */ + +.github-corner:hover .octo-arm { + animation: octocat-wave 560ms ease-in-out; +} + +@keyframes octocat-wave { + 0% { + transform: rotate(0deg); + } + + 20% { + transform: rotate(-25deg); + } + + 40% { + transform: rotate(10deg); + } + + 60% { + transform: rotate(-25deg); + } + + 80% { + transform: rotate(10deg); + } + + 100% { + transform: rotate(0deg); + } +} + +@media (max-width: 500px) { + .github-corner:hover .octo-arm { + animation: none; + } + + .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } +} + +/* @end Github Ribbon - SVG */ diff --git a/drfdocs/templates/drfdocs/base.html b/drfdocs/templates/drfdocs/base.html index 68b55d9..580641a 100644 --- a/drfdocs/templates/drfdocs/base.html +++ b/drfdocs/templates/drfdocs/base.html @@ -1,13 +1,49 @@ +{% load staticfiles %} + + + + DRF Docs + + + + + + + + + + -

Django Rest Frameworks Docs

+ + + + + + + + +
+
+

DRF Docs

+

Documentation for Web APIs made with Django Rest Framework.

+
- {% block content %}{% endblock %} + {% block content %}{% endblock %} + +
diff --git a/drfdocs/templates/drfdocs/home.html b/drfdocs/templates/drfdocs/home.html index be7a304..5a06225 100644 --- a/drfdocs/templates/drfdocs/home.html +++ b/drfdocs/templates/drfdocs/home.html @@ -1,9 +1,13 @@ {% extends "drfdocs/base.html" %} {% block content %} - {% endblock %} diff --git a/drfdocs/views.py b/drfdocs/views.py index e014e3e..f577391 100644 --- a/drfdocs/views.py +++ b/drfdocs/views.py @@ -9,5 +9,5 @@ class DRFDocsView(TemplateView): def get_context_data(self, **kwargs): context = super(DRFDocsView, self).get_context_data(**kwargs) docs = ApiDocumentation() - context['views'] = docs.get_views() + context['endpoints'] = docs.get_endpoints() return context