Djangoテンプレートをデバッグするためのラベル


詳細
Djangoテンプレートには、メソッドを呼び出すことができず、任意のPython式を実行できないなど、多くの制限があります.その設計者はわざとやったと言っていますが、これが良いのか悪いのかは議論しませんが、デバッグ時に任意のPython式を実行する必要があります.Djangoはラベルをカスタマイズするメカニズムを提供し、Pythonのeval関数を加えることで、Djangoテンプレートでも任意のPython式を実行することができます.
set,print,importの3つのラベルを書きました.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 }} 
{% set a = num + len %} Now num value: {{ a }}

出力:

length of list: 3
Now num value: 28

printラベルはもっと簡単です.文法は次のとおりです.

{% print python_expression %}

python_を直接出力しますexpressionの値.上のテストhtmlは次のように書くことができます.

	length of list: {% print len(list) %} 
Now num value: {% print num + len %}

importラベルは、その名の通り、Pythonモジュールをインポートするために使用されます.構文は次のとおりです.

	{% import import_expression [ as alias_name ] %}

test.html

	{% import sys %}
	{% print sys.path %} 

これらの実装は簡単で、直接ここに添付されています.

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)