|
1 | 1 | import inspect
|
2 | 2 | from collections import defaultdict
|
| 3 | +from collections.abc import Callable |
3 | 4 | from time import time
|
4 | 5 |
|
5 | 6 | import wrapt
|
6 | 7 | from debug_toolbar.panels import Panel
|
7 | 8 | from debug_toolbar.panels.sql.utils import contrasting_color_generator
|
8 | 9 | import django
|
9 | 10 | from django.dispatch import Signal
|
| 11 | +from django.urls import resolve |
| 12 | + |
10 | 13 |
|
11 | 14 | if django.VERSION < (3, 2):
|
12 | 15 | from django.utils.translation import ugettext_lazy as _
|
|
23 | 26 | node_element_colors = {}
|
24 | 27 |
|
25 | 28 |
|
| 29 | +@wrapt.decorator |
| 30 | +def profile_method(wrapped, instance, args, kwargs): |
| 31 | + start = time() |
| 32 | + |
| 33 | + result = wrapped(*args, **kwargs) |
| 34 | + end = time() |
| 35 | + |
| 36 | + instance_name = ( |
| 37 | + (wrapped.__self__.__class__.__name__ + ".") |
| 38 | + if hasattr(wrapped, '__self__') else "" |
| 39 | + ) + wrapped.__name__ |
| 40 | + template_rendered.send( |
| 41 | + sender=instance.__class__, |
| 42 | + instance=instance_name, |
| 43 | + start=start, |
| 44 | + end=end, |
| 45 | + processing_timeline=[], |
| 46 | + level=1, |
| 47 | + ) |
| 48 | + return result |
| 49 | + |
| 50 | + |
26 | 51 | def get_nodelist_timeline(nodelist, level):
|
27 | 52 | timeline = []
|
28 | 53 | for node in nodelist:
|
@@ -77,6 +102,22 @@ def __init__(self, *args, **kwargs):
|
77 | 102 |
|
78 | 103 | have_monkey_patched_template_classes = False
|
79 | 104 |
|
| 105 | + def generate_stats(self, request, response): |
| 106 | + match = resolve(request.path) |
| 107 | + func, args, kwargs = match |
| 108 | + view_class = getattr(func, 'view_class', None) |
| 109 | + if view_class and not hasattr(view_class, '_profile_enabled'): |
| 110 | + print(view_class) |
| 111 | + view_class._profile_enabled = True |
| 112 | + for attr in view_class.__dict__: |
| 113 | + print(attr) |
| 114 | + if isinstance(getattr(view_class, attr), Callable): |
| 115 | + setattr( |
| 116 | + view_class, |
| 117 | + attr, |
| 118 | + profile_method(getattr(view_class, attr)), |
| 119 | + ) |
| 120 | + |
80 | 121 | @classmethod
|
81 | 122 | def monkey_patch_template_classes(cls):
|
82 | 123 | if cls.have_monkey_patched_template_classes:
|
@@ -160,7 +201,10 @@ def record(self, instance, start, end, level,
|
160 | 201 | if not self.enabled:
|
161 | 202 | return
|
162 | 203 |
|
163 |
| - template_name = instance.name |
| 204 | + try: |
| 205 | + template_name = instance.name |
| 206 | + except AttributeError: |
| 207 | + template_name = instance |
164 | 208 | # Logic copied from django-debug-toolbar:
|
165 | 209 | # https://github.com/jazzband/django-debug-toolbar/blob/5d095f66fde8f10b45a93c0b35be0a85762b0458/debug_toolbar/panels/templates/panel.py#L77
|
166 | 210 | is_skipped_template = isinstance(template_name, str) and (
|
|
0 commit comments