1
+ import inspect
1
2
from collections import defaultdict
3
+ from time import time
2
4
3
- from django .conf import settings
5
+ import wrapt
6
+ from django .dispatch import Signal
4
7
from django .utils .translation import ugettext_lazy as _
5
8
6
9
from debug_toolbar .panels import Panel
7
10
from debug_toolbar .panels .sql .utils import contrasting_color_generator
8
11
9
- from template_profiler_panel .signals import template_rendered
12
+
13
+ template_rendered = Signal (providing_args = ['instance' , 'start' , 'end' , 'level' ])
10
14
11
15
12
16
class TemplateProfilerPanel (Panel ):
@@ -23,8 +27,56 @@ def __init__(self, *args, **kwargs):
23
27
self .t_min = 0
24
28
self .t_max = 0
25
29
self .total = 0
30
+ self .monkey_patch_template_classes ()
31
+ self .is_enabled = False
32
+ template_rendered .connect (self .record )
26
33
super (TemplateProfilerPanel , self ).__init__ (* args , ** kwargs )
27
34
35
+ have_monkey_patched_template_classes = False
36
+
37
+ @classmethod
38
+ def monkey_patch_template_classes (cls ):
39
+ if cls .have_monkey_patched_template_classes :
40
+ return
41
+
42
+ from django .template import Template as DjangoTemplate
43
+ template_classes = [DjangoTemplate ]
44
+
45
+ try :
46
+ from jinja2 import Template as Jinja2Template
47
+ except ImportError :
48
+ pass
49
+ else :
50
+ template_classes .append (Jinja2Template )
51
+
52
+ @wrapt .decorator
53
+ def render_wrapper (wrapped , instance , args , kwargs ):
54
+ start = time ()
55
+ result = wrapped (* args , ** kwargs )
56
+ end = time ()
57
+
58
+ stack_depth = 1
59
+ current_frame = inspect .currentframe ()
60
+ while True :
61
+ current_frame = current_frame .f_back
62
+ if current_frame is None :
63
+ break
64
+ stack_depth += 1
65
+
66
+ template_rendered .send (
67
+ sender = instance .__class__ ,
68
+ instance = instance ,
69
+ start = start ,
70
+ end = end ,
71
+ level = stack_depth ,
72
+ )
73
+ return result
74
+
75
+ for template_class in template_classes :
76
+ template_class .render = render_wrapper (template_class .render )
77
+
78
+ cls .have_monkey_patched_template_classes = True
79
+
28
80
@property
29
81
def nav_title (self ):
30
82
return _ ('Template Profiler' )
@@ -41,9 +93,11 @@ def title(self):
41
93
def _get_color (self , level ):
42
94
return self .colors .setdefault (level , next (self .color_generator ))
43
95
44
- def record (self , sender , instance , start , end , level , ** kwargs ):
45
- template_name = instance .name
96
+ def record (self , instance , start , end , level , ** kwargs ):
97
+ if not self .enabled :
98
+ return
46
99
100
+ template_name = instance .name
47
101
# Logic copied from django-debug-toolbar:
48
102
# https://github.com/jazzband/django-debug-toolbar/blob/5d095f66fde8f10b45a93c0b35be0a85762b0458/debug_toolbar/panels/templates/panel.py#L77
49
103
is_skipped_template = isinstance (template_name , str ) and (
@@ -69,10 +123,10 @@ def record(self, sender, instance, start, end, level, **kwargs):
69
123
})
70
124
71
125
def enable_instrumentation (self ):
72
- template_rendered . connect ( self .record )
126
+ self .is_enabled = True
73
127
74
128
def disable_instrumentation (self ):
75
- template_rendered . disconnect ( self .record )
129
+ self .is_enabled = False
76
130
77
131
def _calc_p (self , part , whole ):
78
132
return (part / whole ) * 100.0
0 commit comments