from django.template import Variable def patch_resolver(): Variable._resolve_lookup = our_resolver def our_resolver(self, context): current = context how_resolved_steps = [] for bit in self.lookups: how_resolved, current = resolve_bit(current, bit) how_resolved_steps.append((how_resolved, current)) debug(self.lookups, how_resolved_steps) return current def resolve_bit(current, bit): # Strict, does not allow list lookups, for example try: return 'dictionary', current[bit] except (TypeError, AttributeError, KeyError): pass current = getattr(current, bit) if not callable(current): return 'attribute', current if getattr(current, 'alters_data', False): raise Exception('trying to alter data') return 'called attribute', current() def debug(lookups, how_resolved_steps): name = 'context' for i, (how_resolved, value) in enumerate(how_resolved_steps): bit = lookups[i] if how_resolved == 'dictionary': name += "['%s']" % bit elif how_resolved == 'attribute': name += '.%s' % bit else: name += '.%s()' % bit print '%.40s' % name, value