再一个用于调试Django模板的标签

主要用于在Html中递归输出对象的属性,这对调试Django相当有用。

用法:

{% inspect object %}



实现:

from django import template
import re
register = template.Library()

def do_inspect(parser, token):
try:
tag_name, var_name = token.split_contents()
except ValueException:
msg = '%r tag requires a single parameter' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return DumpVarNode(var_name)

import types
method_types = (types.BuiltinFunctionType, types.BuiltinMethodType, types.MethodType, types.FunctionType,)

from django.utils.html import escape
class DumpVarNode(template.Node):
def __init__(self, var_name):
self.var_name = var_name
self.var = template.Variable(var_name)
self._objects = [] # contains travased objects

def render(self, context):
var_value = self.var.resolve(context)
html = '''
<script>
if (!window.jQuery) {
document.write('<scrip' + 't src="http://code.jquery.com/jquery-1.4.2.js" type="text/javascript"></sc' + 'ript>');
}
</script>
<script>
(function($) {
$(function() {
$('.djt_var_head').click(function() {
$('.djt_display_area textarea').val($(this).find('.djt_var_detailed').text())
});
$('.djt_exp').click(function() {
$(this).closest('.djt_var_head').find('+ .djt_var_body').toggle();
var expcol = $(this).toggleClass('djx_expanded');
if (expcol.hasClass('djx_expanded')) {
expcol.html('-');
} else if (varBody.length > 0) {
expcol.html('+');
}
})
});
})(jQuery);
</script>
<style type="text/css">
.djt_render {
font-family: monospace;
color: #333;
line-height: 150%;
}
.djt_var_name {
color: #000;
}
.djt_var_value {
color: #666;
}
.djt_var_body {
padding-left: 2em;
}
.djt_type_type {
color: #00681C;
font-weight: bold;
}
.djt_type_str, .djt_type_int, .djt_type_long, .djt_type_float, .djt_type_bool {
color: #3333CC;
font-weight: bold;
}
.djt_type_instance {
color: #256;
font-weight: bold;
}
.djt_var_id {
/*color: blue;*/
}
</style>'''
html += '<div class="djt_render">'
html += self._render_var(self.var_name, var_value, expand_props=True)
html += '<div class="djt_display_area"><textarea rows="10" cols="80"></textarea></div>'
html += '</div>'
return html

def _render_var(self, var_name, var_value, expand_props=False):
already_exists = any([var_value is x for x in self._objects])
self._objects.append(var_value)

props = self.get_var_props(var_value)
html = '<div class="djt_var">\n'
html += self._render_var_head(var_name, var_value, props, expand_props, exists=already_exists)
html += self._render_var_body(var_value, props, expand_props, exists=already_exists)
html += '</div>'
return html

def _render_var_head(self, var_name, var_value, props, expand_props = False, exists=False):
html = '<div class="djt_var_head">'
if not exists:
html += '<a name="djt_%s"></a>' % id(var_value)
expanded = len(props) == 0 or exists or expand_props
html += '''\
<span class="djt_exp %s">%s</span>
<span class="djt_var_name">%s:</span>
<span class="djt_var_value djt_type_%s">%s</span>
%s
<div class="djt_var_detailed" style="display:none">%s</div>
</div>''' % (
'djx_expanded' if expanded else '',
'-' if expanded else '+',
escape(var_name),
self._value_type(var_value),
self._str_value(var_value),
self._render_return_link(var_value) if exists else '',
self._detailed_str(var_value),
)
return html

def _render_return_link(self, var):
return '<a class="djt_jumplink" href="#djt_%s">here<a/>' % id(var)

def _render_var_body(self, var_value, props, expand_props = False, exists=False):
if len(props) == 0 or exists: return ''

html = '<div class="djt_var_body" %s>' % ('' if expand_props else 'style="display:none"')
for prop_name, prop_value in props:
html += self._render_var(prop_name, prop_value)
html += '</div>'
return html

def _value_type(self, var):
if var is None:
return 'none'
if type(var) in (bool, int, long, float, str, type):
return type(var).__name__
if type(var) in (unicode,):
return 'str'
return 'instance'

def _detailed_str(self, var):
tmp = '''\
type: %s
bases: %s
id: %s
str: "%s"
repr: %r
''' % (
type(var).__name__, type(var).__bases__, id(var),
var, var,
)
return escape(tmp)

def get_var_props(self, var_value):
if isinstance(var_value, (int, long, bool, float, str, unicode)):
return []
if isinstance(var_value, method_types):
return []

props = []
for prop in dir(var_value):
if prop.startswith('_'):
continue
try:
prop_value = getattr(var_value, prop)
# ingore builtin type
if isinstance(prop_value, method_types):
continue

props.append( (prop, prop_value) )
except Exception, e:
props.append( (prop, e) ) # TODO: indicator as error

return props
def _str_value(self, val):
if isinstance(val, (bool, int, long, str, float)):
strval = repr(val)
elif isinstance(val, unicode):
strval = repr(val)[1:]
elif isinstance(val, (list, tuple, dict)):
strval = str(val)
else:
try:
strval = val.__class__.__name__
except:
strval = 'error occured'
return escape(str(strval))

register.tag('inspect', do_inspect)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值