几个用于调试Django模板的标签

Django模板有诸多限制,例如不能调用方法,不能执行任意的Python表达式。它的设计者表示这样做是故意的,我不去争论这样到底是好是坏,但在调试时我们确实需要想执行任意的Python表达式。Django提供了自定义标签的机制,再加上Python的eval函数,使得在Django模板中也能执行任意的Python表达式。

我写了三个标签,分别是set, print和import。set的语法为:

{% set varname = python_expression %}

它会执行python_expression的值,并把它添加到的模板上下文,而后可以用varname引用。
python_expression可以为任意的Python表达式,可以使用模板上下文中的变量。

views.py

return render_to_response('test.html' {
'list': ['a', 'b', 'c'],
'num': 25,
'name': 'marlon',
})


test.html

{% set len = len(list) %}
length of list: {{ len }} <br />
{% set a = num + len %}
Now num value: {{ a }} <br />


输出:

length of list: 3
Now num value: 28


print标签就更简单了,它的语法为:

{% print python_expression %}

它直接输出python_expression的值。上面的test.html可以写成:

length of list: {% print len(list) %} <br />
Now num value: {% print num + len %} <br />



import标签,顾名思义,是用来导入Python模块,它的语法为:

{% import import_expression [ as alias_name ] %}


test.html

{% import sys %}
{% print sys.path %} <br />



它们的实现很简单,直接附在这里:

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

set_regex = re.compile(r'^\s*set\s+(\w+)\s*=\s*(.*)$')
def do_set(parser, token):
m = re.match(set_regex, token.contents)
if m:
name, exp = m.group(1), m.group(2)
return SetNode(name, exp)
else:
raise template.TemplateSyntaxError('{% set varname = python_expression %}')

class SetNode(template.Node):
def __init__(self, varname, expression):
self.varname = varname
self.expression = expression

def render(self, context):
context[self.varname] = eval(self.expression, {}, context)
return ''

register.tag('set', do_set)


print_regex = re.compile(r'^\s*print\s+(.*)$')
def do_print(parser, token):
m = re.match(print_regex, token.contents)
if m:
exp = m.group(1)
return PrintNode(exp)
else:
raise template.TemplateSyntaxError('{% print expression %}')

class PrintNode(template.Node):
def __init__(self, expression):
self.expression = expression

def render(self, context):
obj = eval(self.expression, {}, context)
return str(obj)

register.tag('print', do_print)


import_regex = re.compile(r'^\s*import\s+(\S+)(?:\s+as\s+(\w+))?$')
def do_import(parser, token):
m = re.match(import_regex, token.contents)
if m:
exp = m.group(1)
try:
alias = m.group(2)
except:
alias = None
return ImportNode(exp, alias)
else:
raise template.TemplateSyntaxError('{% import import_expression [ as alias_name ] %}')

class ImportNode(template.Node):
def __init__(self, expression, alias=None):
if not alias: alias = expression
self.expression = expression
self.alias = alias

def render(self, context):
module = __import__(self.expression, {}, context)
context[self.alias] = module
return ''

register.tag('import', do_import)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值