123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- 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
- disabled_panels = dt_settings.get_config()['DISABLE_PANELS']
- panel_path = get_name_from_obj(self)
- # Some panels such as the SQLPanel and TemplatesPanel exist in a
- # panel module, but can be disabled without panel in the path.
- # For that reason, replace .panel. in the path and check for that
- # value in the disabled panels as well.
- disable_panel = (
- panel_path in disabled_panels or
- panel_path.replace('.panel.', '.') in disabled_panels)
- if disable_panel:
- 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, {})
-
- def record_server_timing(self, key, title, value):
- """
- Store data gathered by the panel. ``stats`` is a :class:`dict`.
-
- Each call to ``record_stats`` updates the statistics dictionary.
- """
- data = {key: dict(title=title, value=value)}
- self.toolbar.server_timing_stats.setdefault(self.panel_id, {}).update(data)
-
- def get_server_timing_stats(self):
- """
- Access data stored by the panel. Returns a :class:`dict`.
- """
- return self.toolbar.server_timing_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. This is similar to
- :meth:`generate_stats <debug_toolbar.panels.Panel.generate_stats>`,
- but will be executed on every request. It should be used when either
- the logic needs to be executed on every request or it needs to change
- the response entirely, such as :class:`RedirectsPanel`.
-
- Write panel logic related to the response there. Post-process data
- gathered while the view executed. Save data with :meth:`record_stats`.
-
- Return a response to overwrite the existing response.
- """
-
- def generate_stats(self, request, response):
- """
- Similar to :meth:`process_response
- <debug_toolbar.panels.Panel.process_response>`,
- but may not be executed on every request. This will only be called if
- the toolbar will be inserted into the request.
-
- Write panel logic related to the response there. Post-process data
- gathered while the view executed. Save data with :meth:`record_stats`.
-
- Does not return a value.
- """
-
- def generate_server_timing(self, request, response):
- """
- Similar to :meth:`generate_stats
- <debug_toolbar.panels.Panel.generate_stats>`,
-
- Generate stats for Server Timing https://w3c.github.io/server-timing/
-
- Does not return a value.
- """
-
-
- # 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)
|