apps.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import inspect
  2. from django.apps import AppConfig
  3. from django.conf import settings
  4. from django.core.checks import Warning, register
  5. from django.middleware.gzip import GZipMiddleware
  6. from django.utils.module_loading import import_string
  7. from django.utils.translation import gettext_lazy as _
  8. from debug_toolbar import settings as dt_settings
  9. class DebugToolbarConfig(AppConfig):
  10. name = "debug_toolbar"
  11. verbose_name = _("Debug Toolbar")
  12. def ready(self):
  13. from debug_toolbar.toolbar import DebugToolbar
  14. # Import the panels when the app is ready and call their ready() methods. This
  15. # allows panels like CachePanel to enable their instrumentation immediately.
  16. for cls in DebugToolbar.get_panel_classes():
  17. cls.ready()
  18. def check_template_config(config):
  19. """
  20. Checks if a template configuration is valid.
  21. The toolbar requires either the toolbars to be unspecified or
  22. ``django.template.loaders.app_directories.Loader`` to be
  23. included in the loaders.
  24. If custom loaders are specified, then APP_DIRS must be True.
  25. """
  26. app_dirs = config.get("APP_DIRS", False)
  27. loaders = config.get("OPTIONS", {}).get("loaders", None)
  28. # By default the app loader is included.
  29. has_app_loaders = (
  30. loaders is None or "django.template.loaders.app_directories.Loader" in loaders
  31. )
  32. return has_app_loaders or app_dirs
  33. @register
  34. def check_middleware(app_configs, **kwargs):
  35. from debug_toolbar.middleware import DebugToolbarMiddleware
  36. errors = []
  37. gzip_index = None
  38. debug_toolbar_indexes = []
  39. if all(not check_template_config(config) for config in settings.TEMPLATES):
  40. errors.append(
  41. Warning(
  42. "At least one DjangoTemplates TEMPLATES configuration needs "
  43. "to use django.template.loaders.app_directories.Loader or "
  44. "have APP_DIRS set to True.",
  45. hint=(
  46. "Include django.template.loaders.app_directories.Loader "
  47. 'in ["OPTIONS"]["loaders"]. Alternatively use '
  48. "APP_DIRS=True for at least one "
  49. "django.template.backends.django.DjangoTemplates "
  50. "backend configuration."
  51. ),
  52. id="debug_toolbar.W006",
  53. )
  54. )
  55. # If old style MIDDLEWARE_CLASSES is being used, report an error.
  56. if settings.is_overridden("MIDDLEWARE_CLASSES"):
  57. errors.append(
  58. Warning(
  59. "debug_toolbar is incompatible with MIDDLEWARE_CLASSES setting.",
  60. hint="Use MIDDLEWARE instead of MIDDLEWARE_CLASSES",
  61. id="debug_toolbar.W004",
  62. )
  63. )
  64. return errors
  65. # Determine the indexes which gzip and/or the toolbar are installed at
  66. for i, middleware in enumerate(settings.MIDDLEWARE):
  67. if is_middleware_class(GZipMiddleware, middleware):
  68. gzip_index = i
  69. elif is_middleware_class(DebugToolbarMiddleware, middleware):
  70. debug_toolbar_indexes.append(i)
  71. if not debug_toolbar_indexes:
  72. # If the toolbar does not appear, report an error.
  73. errors.append(
  74. Warning(
  75. "debug_toolbar.middleware.DebugToolbarMiddleware is missing "
  76. "from MIDDLEWARE.",
  77. hint="Add debug_toolbar.middleware.DebugToolbarMiddleware to "
  78. "MIDDLEWARE.",
  79. id="debug_toolbar.W001",
  80. )
  81. )
  82. elif len(debug_toolbar_indexes) != 1:
  83. # If the toolbar appears multiple times, report an error.
  84. errors.append(
  85. Warning(
  86. "debug_toolbar.middleware.DebugToolbarMiddleware occurs "
  87. "multiple times in MIDDLEWARE.",
  88. hint="Load debug_toolbar.middleware.DebugToolbarMiddleware only "
  89. "once in MIDDLEWARE.",
  90. id="debug_toolbar.W002",
  91. )
  92. )
  93. elif gzip_index is not None and debug_toolbar_indexes[0] < gzip_index:
  94. # If the toolbar appears before the gzip index, report an error.
  95. errors.append(
  96. Warning(
  97. "debug_toolbar.middleware.DebugToolbarMiddleware occurs before "
  98. "django.middleware.gzip.GZipMiddleware in MIDDLEWARE.",
  99. hint="Move debug_toolbar.middleware.DebugToolbarMiddleware to "
  100. "after django.middleware.gzip.GZipMiddleware in MIDDLEWARE.",
  101. id="debug_toolbar.W003",
  102. )
  103. )
  104. return errors
  105. @register
  106. def check_panel_configs(app_configs, **kwargs):
  107. """Allow each panel to check the toolbar's integration for their its own purposes."""
  108. from debug_toolbar.toolbar import DebugToolbar
  109. errors = []
  110. for panel_class in DebugToolbar.get_panel_classes():
  111. for check_message in panel_class.run_checks():
  112. errors.append(check_message)
  113. return errors
  114. def is_middleware_class(middleware_class, middleware_path):
  115. try:
  116. middleware_cls = import_string(middleware_path)
  117. except ImportError:
  118. return
  119. return inspect.isclass(middleware_cls) and issubclass(
  120. middleware_cls, middleware_class
  121. )
  122. @register
  123. def check_panels(app_configs, **kwargs):
  124. errors = []
  125. panels = dt_settings.get_panels()
  126. if not panels:
  127. errors.append(
  128. Warning(
  129. "Setting DEBUG_TOOLBAR_PANELS is empty.",
  130. hint="Set DEBUG_TOOLBAR_PANELS to a non-empty list in your "
  131. "settings.py.",
  132. id="debug_toolbar.W005",
  133. )
  134. )
  135. return errors