aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAymeric Augustin2013-11-24 17:13:11 +0100
committerAymeric Augustin2013-11-24 17:15:59 +0100
commitf52f266c691fd8bb80b21ab2a983118b914c04fa (patch)
tree3cafd92796aae91e63abc3958ab1642745b6cfd8
parentc92f710125218755c275ae98581a4305e57fd3fa (diff)
downloaddjango-debug-toolbar-f52f266c691fd8bb80b21ab2a983118b914c04fa.tar.bz2
Clean up and document the Panel API.
-rw-r--r--debug_toolbar/panels/__init__.py141
-rw-r--r--docs/conf.py3
-rw-r--r--docs/panels.rst40
3 files changed, 155 insertions, 29 deletions
diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py
index d1a90d0..39c9d80 100644
--- a/debug_toolbar/panels/__init__.py
+++ b/debug_toolbar/panels/__init__.py
@@ -9,28 +9,17 @@ class Panel(object):
"""
Base class for panels.
"""
- # name = 'Base'
- # template = 'debug_toolbar/panels/base.html'
-
- # If content returns something, set to True in subclass
- has_content = False
# We'll maintain a local context instance so we can expose our template
- # context variables to panels which need them:
+ # context variables to panels which need them. (But see issue #450.)
context = {}
- # Panel methods
+ # Private panel methods
def __init__(self, toolbar, context={}):
self.toolbar = toolbar
self.context.update(context)
- def content(self):
- if self.has_content:
- context = self.context.copy()
- context.update(self.get_stats())
- return render_to_string(self.template, context)
-
@property
def panel_id(self):
return self.__class__.__name__
@@ -39,52 +28,146 @@ class Panel(object):
def enabled(self):
return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, 'on') == 'on'
- # URLs for panel-specific views
-
- @classmethod
- def get_urls(cls):
- return []
-
- # Titles and subtitles
+ # Titles and content
+ @property
def nav_title(self):
- """Title showing in sidebar"""
- raise NotImplementedError
+ """
+ Title shown in the side bar. Defaults to :attr:`title`.
+ """
+ return self.title
+ @property
def nav_subtitle(self):
- """Subtitle showing under title in sidebar"""
+ """
+ Subtitle shown in the side bar. Defaults to the empty string.
+ """
return ''
+ @property
+ def has_content(self):
+ """
+ ``True`` if the panel can be displayed in full screen, ``False`` if
+ it's only shown in the side bar. Defaults to ``True``.
+ """
+ return True
+
+ @property
def title(self):
- """Title showing in panel"""
+ """
+ Title shown in the panel when it's displayed in full screen.
+
+ Mandatory, unless the panel sets :attr:`has_content` to ``False``.
+ """
+ raise NotImplementedError
+
+ @property
+ def template(self):
+ """
+ Template used to render :attr:`content`.
+
+ Mandatory, unless the panel sets :attr:`has_content` to ``False`` or
+ overrides `attr`:content`.
+ """
raise NotImplementedError
+ @property
+ def content(self):
+ """
+ Content of the panel when it's displayed in full screen.
+
+ By default this renders the template defined by :attr:`template`.
+ Statistics stored with :meth:`record_stats` are available in the
+ template's context.
+ """
+ if self.has_content:
+ context = self.context.copy()
+ context.update(self.get_stats())
+ return render_to_string(self.template, context)
+
+ # URLs for panel-specific views
+
+ @classmethod
+ def get_urls(cls):
+ """
+ Return URLpatterns, if the panel has its own views.
+ """
+ return []
+
# Enable and disable (expensive) instrumentation, must be idempotent
def enable_instrumentation(self):
- pass
+ """
+ Enable instrumentation to gather data for this panel.
+
+ This usually means monkey-patching (!) or registering signal
+ receivers. Any instrumentation with a non-negligible effect on
+ performance should be installed by this method rather than at import
+ time.
+
+ Unless the toolbar or this panel is disabled, this method will be
+ called early in :class:`DebugToolbarMiddleware.process_request`. It
+ should be idempotent.
+ """
def disable_instrumentation(self):
- pass
+ """
+ Disable instrumentation to gather data for this panel.
+
+ This is the opposite of :meth:`enable_instrumentation`.
+
+ Unless the toolbar or this panel is disabled, this method will be
+ called late in :class:`DebugToolbarMiddleware.process_response`. It
+ should be idempotent.
+ """
# Store and retrieve stats (shared between panels for no good reason)
def record_stats(self, stats):
+ """
+ Store data gathered by the panel. ``stats`` is a :class:`dict`.
+
+ Each call to ``record_stats`` updates the statistics dictionary.
+ """
self.toolbar.stats.setdefault(self.panel_id, {}).update(stats)
def get_stats(self):
+ """
+ Access data stored by the panel. Returns a :class:`dict`.
+ """
return self.toolbar.stats.get(self.panel_id, {})
# Standard middleware methods
def process_request(self, request):
- pass
+ """
+ Like process_request_ in Django's middleware.
+
+ Write panel logic related to the request there. Save data with
+ :meth:`record_stats`.
+
+ .. _process_request: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
+ """
def process_view(self, request, view_func, view_args, view_kwargs):
- pass
+ """
+ Like process_view_ in Django's middleware.
+
+ Write panel logic related to the view there. Save data with
+ :meth:`record_stats`.
+
+ .. _process_view: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
+ """
def process_response(self, request, response):
- pass
+ """
+ Like process_response_ in Django's middleware.
+
+ Write panel logic related to the response there. Post-process data
+ gathered while the view executed. Save data with :meth:`record_stats`.
+
+ .. _process_response: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
+ """
# Backward-compatibility for 1.0, remove in 2.0.
diff --git a/docs/conf.py b/docs/conf.py
index c2fcade..abde59b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -15,6 +15,9 @@
import sys
import os
+os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings'
+sys.path.append(os.path.dirname(os.path.dirname(__file__)))
+
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
diff --git a/docs/panels.rst b/docs/panels.rst
index 39ddf7f..c766780 100644
--- a/docs/panels.rst
+++ b/docs/panels.rst
@@ -212,3 +212,43 @@ URL: https://github.com/playfire/django-debug-toolbar-user-panel
Path: ``debug_toolbar_user_panel.panels.UserPanel``
Easily switch between logged in users, see properties of current user.
+
+API for third-party panels
+--------------------------
+
+Third-party panels must subclass :class:`~debug_toolbar.panels.Panel`,
+according to the public API described below. Unless noted otherwise, all
+methods are optional.
+
+Panels can ship their own templates, static files and views. They're no public
+CSS or JavaScript API at this time, but they can assume jQuery is available.
+
+.. autoclass:: debug_toolbar.panels.Panel(*args, **kwargs)
+
+ .. autoattribute:: debug_toolbar.panels.Panel.nav_title
+
+ .. autoattribute:: debug_toolbar.panels.Panel.nav_subtitle
+
+ .. autoattribute:: debug_toolbar.panels.Panel.has_content
+
+ .. autoattribute:: debug_toolbar.panels.Panel.title
+
+ .. autoattribute:: debug_toolbar.panels.Panel.template
+
+ .. autoattribute:: debug_toolbar.panels.Panel.content
+
+ .. automethod:: debug_toolbar.panels.Panel.get_urls
+
+ .. automethod:: debug_toolbar.panels.Panel.enable_instrumentation
+
+ .. automethod:: debug_toolbar.panels.Panel.disable_instrumentation
+
+ .. automethod:: debug_toolbar.panels.Panel.record_stats
+
+ .. automethod:: debug_toolbar.panels.Panel.get_stats
+
+ .. automethod:: debug_toolbar.panels.Panel.process_request
+
+ .. automethod:: debug_toolbar.panels.Panel.process_view
+
+ .. automethod:: debug_toolbar.panels.Panel.process_response