Skip to content

Commit f52f266

Browse files
committed
Clean up and document the Panel API.
1 parent c92f710 commit f52f266

File tree

3 files changed

+155
-29
lines changed

3 files changed

+155
-29
lines changed

debug_toolbar/panels/__init__.py

Lines changed: 112 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,17 @@ class Panel(object):
99
"""
1010
Base class for panels.
1111
"""
12-
# name = 'Base'
13-
# template = 'debug_toolbar/panels/base.html'
14-
15-
# If content returns something, set to True in subclass
16-
has_content = False
1712

1813
# We'll maintain a local context instance so we can expose our template
19-
# context variables to panels which need them:
14+
# context variables to panels which need them. (But see issue #450.)
2015
context = {}
2116

22-
# Panel methods
17+
# Private panel methods
2318

2419
def __init__(self, toolbar, context={}):
2520
self.toolbar = toolbar
2621
self.context.update(context)
2722

28-
def content(self):
29-
if self.has_content:
30-
context = self.context.copy()
31-
context.update(self.get_stats())
32-
return render_to_string(self.template, context)
33-
3423
@property
3524
def panel_id(self):
3625
return self.__class__.__name__
@@ -39,52 +28,146 @@ def panel_id(self):
3928
def enabled(self):
4029
return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, 'on') == 'on'
4130

42-
# URLs for panel-specific views
43-
44-
@classmethod
45-
def get_urls(cls):
46-
return []
47-
48-
# Titles and subtitles
31+
# Titles and content
4932

33+
@property
5034
def nav_title(self):
51-
"""Title showing in sidebar"""
52-
raise NotImplementedError
35+
"""
36+
Title shown in the side bar. Defaults to :attr:`title`.
37+
"""
38+
return self.title
5339

40+
@property
5441
def nav_subtitle(self):
55-
"""Subtitle showing under title in sidebar"""
42+
"""
43+
Subtitle shown in the side bar. Defaults to the empty string.
44+
"""
5645
return ''
5746

47+
@property
48+
def has_content(self):
49+
"""
50+
``True`` if the panel can be displayed in full screen, ``False`` if
51+
it's only shown in the side bar. Defaults to ``True``.
52+
"""
53+
return True
54+
55+
@property
5856
def title(self):
59-
"""Title showing in panel"""
57+
"""
58+
Title shown in the panel when it's displayed in full screen.
59+
60+
Mandatory, unless the panel sets :attr:`has_content` to ``False``.
61+
"""
62+
raise NotImplementedError
63+
64+
@property
65+
def template(self):
66+
"""
67+
Template used to render :attr:`content`.
68+
69+
Mandatory, unless the panel sets :attr:`has_content` to ``False`` or
70+
overrides `attr`:content`.
71+
"""
6072
raise NotImplementedError
6173

74+
@property
75+
def content(self):
76+
"""
77+
Content of the panel when it's displayed in full screen.
78+
79+
By default this renders the template defined by :attr:`template`.
80+
Statistics stored with :meth:`record_stats` are available in the
81+
template's context.
82+
"""
83+
if self.has_content:
84+
context = self.context.copy()
85+
context.update(self.get_stats())
86+
return render_to_string(self.template, context)
87+
88+
# URLs for panel-specific views
89+
90+
@classmethod
91+
def get_urls(cls):
92+
"""
93+
Return URLpatterns, if the panel has its own views.
94+
"""
95+
return []
96+
6297
# Enable and disable (expensive) instrumentation, must be idempotent
6398

6499
def enable_instrumentation(self):
65-
pass
100+
"""
101+
Enable instrumentation to gather data for this panel.
102+
103+
This usually means monkey-patching (!) or registering signal
104+
receivers. Any instrumentation with a non-negligible effect on
105+
performance should be installed by this method rather than at import
106+
time.
107+
108+
Unless the toolbar or this panel is disabled, this method will be
109+
called early in :class:`DebugToolbarMiddleware.process_request`. It
110+
should be idempotent.
111+
"""
66112

67113
def disable_instrumentation(self):
68-
pass
114+
"""
115+
Disable instrumentation to gather data for this panel.
116+
117+
This is the opposite of :meth:`enable_instrumentation`.
118+
119+
Unless the toolbar or this panel is disabled, this method will be
120+
called late in :class:`DebugToolbarMiddleware.process_response`. It
121+
should be idempotent.
122+
"""
69123

70124
# Store and retrieve stats (shared between panels for no good reason)
71125

72126
def record_stats(self, stats):
127+
"""
128+
Store data gathered by the panel. ``stats`` is a :class:`dict`.
129+
130+
Each call to ``record_stats`` updates the statistics dictionary.
131+
"""
73132
self.toolbar.stats.setdefault(self.panel_id, {}).update(stats)
74133

75134
def get_stats(self):
135+
"""
136+
Access data stored by the panel. Returns a :class:`dict`.
137+
"""
76138
return self.toolbar.stats.get(self.panel_id, {})
77139

78140
# Standard middleware methods
79141

80142
def process_request(self, request):
81-
pass
143+
"""
144+
Like process_request_ in Django's middleware.
145+
146+
Write panel logic related to the request there. Save data with
147+
:meth:`record_stats`.
148+
149+
.. _process_request: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
150+
"""
82151

83152
def process_view(self, request, view_func, view_args, view_kwargs):
84-
pass
153+
"""
154+
Like process_view_ in Django's middleware.
155+
156+
Write panel logic related to the view there. Save data with
157+
:meth:`record_stats`.
158+
159+
.. _process_view: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
160+
"""
85161

86162
def process_response(self, request, response):
87-
pass
163+
"""
164+
Like process_response_ in Django's middleware.
165+
166+
Write panel logic related to the response there. Post-process data
167+
gathered while the view executed. Save data with :meth:`record_stats`.
168+
169+
.. _process_response: https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-request
170+
"""
88171

89172

90173
# Backward-compatibility for 1.0, remove in 2.0.

docs/conf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import sys
1616
import os
1717

18+
os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings'
19+
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
20+
1821
# If extensions (or modules to document with autodoc) are in another directory,
1922
# add these directories to sys.path here. If the directory is relative to the
2023
# documentation root, use os.path.abspath to make it absolute, like shown here.

docs/panels.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,43 @@ URL: https://github.com/playfire/django-debug-toolbar-user-panel
212212
Path: ``debug_toolbar_user_panel.panels.UserPanel``
213213

214214
Easily switch between logged in users, see properties of current user.
215+
216+
API for third-party panels
217+
--------------------------
218+
219+
Third-party panels must subclass :class:`~debug_toolbar.panels.Panel`,
220+
according to the public API described below. Unless noted otherwise, all
221+
methods are optional.
222+
223+
Panels can ship their own templates, static files and views. They're no public
224+
CSS or JavaScript API at this time, but they can assume jQuery is available.
225+
226+
.. autoclass:: debug_toolbar.panels.Panel(*args, **kwargs)
227+
228+
.. autoattribute:: debug_toolbar.panels.Panel.nav_title
229+
230+
.. autoattribute:: debug_toolbar.panels.Panel.nav_subtitle
231+
232+
.. autoattribute:: debug_toolbar.panels.Panel.has_content
233+
234+
.. autoattribute:: debug_toolbar.panels.Panel.title
235+
236+
.. autoattribute:: debug_toolbar.panels.Panel.template
237+
238+
.. autoattribute:: debug_toolbar.panels.Panel.content
239+
240+
.. automethod:: debug_toolbar.panels.Panel.get_urls
241+
242+
.. automethod:: debug_toolbar.panels.Panel.enable_instrumentation
243+
244+
.. automethod:: debug_toolbar.panels.Panel.disable_instrumentation
245+
246+
.. automethod:: debug_toolbar.panels.Panel.record_stats
247+
248+
.. automethod:: debug_toolbar.panels.Panel.get_stats
249+
250+
.. automethod:: debug_toolbar.panels.Panel.process_request
251+
252+
.. automethod:: debug_toolbar.panels.Panel.process_view
253+
254+
.. automethod:: debug_toolbar.panels.Panel.process_response

0 commit comments

Comments
 (0)