Django REST framework has a nice html-based interface that, for every one of your REST views, renders the docstring as an explanation at the top of the page.
Those views, they’re class based views, at least the ones I use. I’m making views that ought to be base views for other Django app’s API. We have a bunch of django apps for various data sources that can present their data in more or less the same way.
So… I’ve put a decent docstring, explaining the API, in my base views. Only… they didn’t show up in the interface for the subclasses. Apparently docstrings aren’t inherited by subclasses! So I asked a question on stack overflow and promptly got an answer.
What I ended up doing was modifying .get_description()
, the method Django
REST framework uses to grab and render the docstring:
import inspect # Fancy standardlibrary Python internal inspection tool.
import docutils
from django.contrib.admindocs.utils import trim_docstring
from django.utils.safestring import mark_safe
....
class MyBaseAPIView(...):
def get_description(self, html=False):
description = self.__doc__ # Our docstring.
if description is None:
# Try and grab it from our parents.
try:
description = next(
cls.__doc__ for cls in inspect.getmro(type(self))
if cls.__doc__ is not None)
except StopIteration:
pass
description = trim_docstring(description)
if html:
# Render with restructured text instead of markdown.
parts = docutils.core.publish_parts(description,
writer_name='html')
return mark_safe(parts['fragment'])
return description
This method is a customization of Django REST framework’s. There are two changes:
Our parent’s docstring is used if we don’t have one ourselves. This makes it easy to use a base class with proper documentation on which items to expect. The documentation is propagated to every API that uses the base class.
The docstring is parsed with restructuredtext syntax instead of markdown (markdown is preferred by Django REST framework).
Hurray for class based views! Because it is an object oriented structure,
it is easy to overwrite parts of functionality. And easy to provide methods to
actually do so (like the .get_description()
I modified).
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):