Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

__init__.py 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. from __future__ import absolute_import, unicode_literals
  2. import warnings
  3. from django.template.loader import render_to_string
  4. from debug_toolbar import settings as dt_settings
  5. from debug_toolbar.utils import get_name_from_obj
  6. class Panel(object):
  7. """
  8. Base class for panels.
  9. """
  10. def __init__(self, toolbar):
  11. self.toolbar = toolbar
  12. # Private panel properties
  13. @property
  14. def panel_id(self):
  15. return self.__class__.__name__
  16. @property
  17. def enabled(self):
  18. # Check to see if settings has a default value for it
  19. disabled_panels = dt_settings.get_config()['DISABLE_PANELS']
  20. panel_path = get_name_from_obj(self)
  21. # Some panels such as the SQLPanel and TemplatesPanel exist in a
  22. # panel module, but can be disabled without panel in the path.
  23. # For that reason, replace .panel. in the path and check for that
  24. # value in the disabled panels as well.
  25. disable_panel = (
  26. panel_path in disabled_panels or
  27. panel_path.replace('.panel.', '.') in disabled_panels)
  28. if disable_panel:
  29. default = 'off'
  30. else:
  31. default = 'on'
  32. # The user's cookies should override the default value
  33. return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, default) == 'on'
  34. # Titles and content
  35. @property
  36. def nav_title(self):
  37. """
  38. Title shown in the side bar. Defaults to :attr:`title`.
  39. """
  40. return self.title
  41. @property
  42. def nav_subtitle(self):
  43. """
  44. Subtitle shown in the side bar. Defaults to the empty string.
  45. """
  46. return ''
  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. @property
  55. def title(self):
  56. """
  57. Title shown in the panel when it's displayed in full screen.
  58. Mandatory, unless the panel sets :attr:`has_content` to ``False``.
  59. """
  60. raise NotImplementedError
  61. @property
  62. def template(self):
  63. """
  64. Template used to render :attr:`content`.
  65. Mandatory, unless the panel sets :attr:`has_content` to ``False`` or
  66. overrides `attr`:content`.
  67. """
  68. raise NotImplementedError
  69. @property
  70. def content(self):
  71. """
  72. Content of the panel when it's displayed in full screen.
  73. By default this renders the template defined by :attr:`template`.
  74. Statistics stored with :meth:`record_stats` are available in the
  75. template's context.
  76. """
  77. if self.has_content:
  78. return render_to_string(self.template, self.get_stats())
  79. # URLs for panel-specific views
  80. @classmethod
  81. def get_urls(cls):
  82. """
  83. Return URLpatterns, if the panel has its own views.
  84. """
  85. return []
  86. # Enable and disable (expensive) instrumentation, must be idempotent
  87. def enable_instrumentation(self):
  88. """
  89. Enable instrumentation to gather data for this panel.
  90. This usually means monkey-patching (!) or registering signal
  91. receivers. Any instrumentation with a non-negligible effect on
  92. performance should be installed by this method rather than at import
  93. time.
  94. Unless the toolbar or this panel is disabled, this method will be
  95. called early in :class:`DebugToolbarMiddleware.process_request`. It
  96. should be idempotent.
  97. """
  98. def disable_instrumentation(self):
  99. """
  100. Disable instrumentation to gather data for this panel.
  101. This is the opposite of :meth:`enable_instrumentation`.
  102. Unless the toolbar or this panel is disabled, this method will be
  103. called late in :class:`DebugToolbarMiddleware.process_response`. It
  104. should be idempotent.
  105. """
  106. # Store and retrieve stats (shared between panels for no good reason)
  107. def record_stats(self, stats):
  108. """
  109. Store data gathered by the panel. ``stats`` is a :class:`dict`.
  110. Each call to ``record_stats`` updates the statistics dictionary.
  111. """
  112. self.toolbar.stats.setdefault(self.panel_id, {}).update(stats)
  113. def get_stats(self):
  114. """
  115. Access data stored by the panel. Returns a :class:`dict`.
  116. """
  117. return self.toolbar.stats.get(self.panel_id, {})
  118. def record_server_timing(self, key, title, value):
  119. """
  120. Store data gathered by the panel. ``stats`` is a :class:`dict`.
  121. Each call to ``record_stats`` updates the statistics dictionary.
  122. """
  123. data = {key: dict(title=title, value=value)}
  124. self.toolbar.server_timing_stats.setdefault(self.panel_id, {}).update(data)
  125. def get_server_timing_stats(self):
  126. """
  127. Access data stored by the panel. Returns a :class:`dict`.
  128. """
  129. return self.toolbar.server_timing_stats.get(self.panel_id, {})
  130. # Standard middleware methods
  131. def process_request(self, request):
  132. """
  133. Like process_request in Django's middleware.
  134. Write panel logic related to the request there. Save data with
  135. :meth:`record_stats`.
  136. """
  137. def process_view(self, request, view_func, view_args, view_kwargs):
  138. """
  139. Like process_view in Django's middleware.
  140. Write panel logic related to the view there. Save data with
  141. :meth:`record_stats`.
  142. """
  143. def process_response(self, request, response):
  144. """
  145. Like process_response in Django's middleware. This is similar to
  146. :meth:`generate_stats <debug_toolbar.panels.Panel.generate_stats>`,
  147. but will be executed on every request. It should be used when either
  148. the logic needs to be executed on every request or it needs to change
  149. the response entirely, such as :class:`RedirectsPanel`.
  150. Write panel logic related to the response there. Post-process data
  151. gathered while the view executed. Save data with :meth:`record_stats`.
  152. Return a response to overwrite the existing response.
  153. """
  154. def generate_stats(self, request, response):
  155. """
  156. Similar to :meth:`process_response
  157. <debug_toolbar.panels.Panel.process_response>`,
  158. but may not be executed on every request. This will only be called if
  159. the toolbar will be inserted into the request.
  160. Write panel logic related to the response there. Post-process data
  161. gathered while the view executed. Save data with :meth:`record_stats`.
  162. Does not return a value.
  163. """
  164. def generate_server_timing(self, request, response):
  165. """
  166. Similar to :meth:`generate_stats
  167. <debug_toolbar.panels.Panel.generate_stats>`,
  168. Generate stats for Server Timing https://w3c.github.io/server-timing/
  169. Does not return a value.
  170. """
  171. # Backward-compatibility for 1.0, remove in 2.0.
  172. class DebugPanel(Panel):
  173. def __init__(self, *args, **kwargs):
  174. warnings.warn("DebugPanel was renamed to Panel.", DeprecationWarning)
  175. super(DebugPanel, self).__init__(*args, **kwargs)