1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
from __future__ import absolute_import, unicode_literals
import warnings
from django.template.loader import render_to_string
from debug_toolbar import settings as dt_settings
from debug_toolbar.utils import get_name_from_obj
class Panel(object):
"""
Base class for panels.
"""
def __init__(self, toolbar):
self.toolbar = toolbar
# Private panel properties
@property
def panel_id(self):
return self.__class__.__name__
@property
def enabled(self):
# Check to see if settings has a default value for it
if get_name_from_obj(self) in dt_settings.CONFIG['DISABLE_PANELS']:
default = 'off'
else:
default = 'on'
# The user's cookies should override the default value
return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, default) == 'on'
# Titles and content
@property
def nav_title(self):
"""
Title shown in the side bar. Defaults to :attr:`title`.
"""
return self.title
@property
def nav_subtitle(self):
"""
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 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:
return render_to_string(self.template, self.get_stats())
# 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):
"""
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):
"""
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):
"""
Like process_request in Django's middleware.
Write panel logic related to the request there. Save data with
:meth:`record_stats`.
"""
def process_view(self, request, view_func, view_args, view_kwargs):
"""
Like process_view in Django's middleware.
Write panel logic related to the view there. Save data with
:meth:`record_stats`.
"""
def process_response(self, request, response):
"""
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`.
"""
# Backward-compatibility for 1.0, remove in 2.0.
class DebugPanel(Panel):
def __init__(self, *args, **kwargs):
warnings.warn("DebugPanel was renamed to Panel.", DeprecationWarning)
super(DebugPanel, self).__init__(*args, **kwargs)
|