Most of the hard work for this was done by akaihola. There are still possibly some problems with the i18n template tags, since they are written quite differently and a few other bug fixes have to made before they can be fixed. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10119 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a6f429e37e
commit
7db24dd2b0
|
@ -39,7 +39,7 @@ class CommentNode(Node):
|
||||||
|
|
||||||
class CycleNode(Node):
|
class CycleNode(Node):
|
||||||
def __init__(self, cyclevars, variable_name=None):
|
def __init__(self, cyclevars, variable_name=None):
|
||||||
self.cycle_iter = itertools_cycle([Variable(v) for v in cyclevars])
|
self.cycle_iter = itertools_cycle(cyclevars)
|
||||||
self.variable_name = variable_name
|
self.variable_name = variable_name
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
|
@ -70,14 +70,11 @@ class FilterNode(Node):
|
||||||
|
|
||||||
class FirstOfNode(Node):
|
class FirstOfNode(Node):
|
||||||
def __init__(self, vars):
|
def __init__(self, vars):
|
||||||
self.vars = map(Variable, vars)
|
self.vars = vars
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
for var in self.vars:
|
for var in self.vars:
|
||||||
try:
|
value = var.resolve(context)
|
||||||
value = var.resolve(context)
|
|
||||||
except VariableDoesNotExist:
|
|
||||||
continue
|
|
||||||
if value:
|
if value:
|
||||||
return smart_unicode(value)
|
return smart_unicode(value)
|
||||||
return u''
|
return u''
|
||||||
|
@ -169,7 +166,7 @@ class IfChangedNode(Node):
|
||||||
def __init__(self, nodelist_true, nodelist_false, *varlist):
|
def __init__(self, nodelist_true, nodelist_false, *varlist):
|
||||||
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
||||||
self._last_seen = None
|
self._last_seen = None
|
||||||
self._varlist = map(Variable, varlist)
|
self._varlist = varlist
|
||||||
self._id = str(id(self))
|
self._id = str(id(self))
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
|
@ -180,7 +177,7 @@ class IfChangedNode(Node):
|
||||||
if self._varlist:
|
if self._varlist:
|
||||||
# Consider multiple parameters. This automatically behaves
|
# Consider multiple parameters. This automatically behaves
|
||||||
# like an OR evaluation of the multiple variables.
|
# like an OR evaluation of the multiple variables.
|
||||||
compare_to = [var.resolve(context) for var in self._varlist]
|
compare_to = [var.resolve(context, True) for var in self._varlist]
|
||||||
else:
|
else:
|
||||||
compare_to = self.nodelist_true.render(context)
|
compare_to = self.nodelist_true.render(context)
|
||||||
except VariableDoesNotExist:
|
except VariableDoesNotExist:
|
||||||
|
@ -200,7 +197,7 @@ class IfChangedNode(Node):
|
||||||
|
|
||||||
class IfEqualNode(Node):
|
class IfEqualNode(Node):
|
||||||
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
|
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
|
||||||
self.var1, self.var2 = Variable(var1), Variable(var2)
|
self.var1, self.var2 = var1, var2
|
||||||
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
||||||
self.negate = negate
|
self.negate = negate
|
||||||
|
|
||||||
|
@ -208,14 +205,8 @@ class IfEqualNode(Node):
|
||||||
return "<IfEqualNode>"
|
return "<IfEqualNode>"
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
try:
|
val1 = self.var1.resolve(context, True)
|
||||||
val1 = self.var1.resolve(context)
|
val2 = self.var2.resolve(context, True)
|
||||||
except VariableDoesNotExist:
|
|
||||||
val1 = None
|
|
||||||
try:
|
|
||||||
val2 = self.var2.resolve(context)
|
|
||||||
except VariableDoesNotExist:
|
|
||||||
val2 = None
|
|
||||||
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
|
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
|
||||||
return self.nodelist_true.render(context)
|
return self.nodelist_true.render(context)
|
||||||
return self.nodelist_false.render(context)
|
return self.nodelist_false.render(context)
|
||||||
|
@ -371,11 +362,10 @@ class URLNode(Node):
|
||||||
args = [arg.resolve(context) for arg in self.args]
|
args = [arg.resolve(context) for arg in self.args]
|
||||||
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
|
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
|
||||||
for k, v in self.kwargs.items()])
|
for k, v in self.kwargs.items()])
|
||||||
|
|
||||||
|
|
||||||
# Try to look up the URL twice: once given the view name, and again
|
# Try to look up the URL twice: once given the view name, and again
|
||||||
# relative to what we guess is the "main" app. If they both fail,
|
# relative to what we guess is the "main" app. If they both fail,
|
||||||
# re-raise the NoReverseMatch unless we're using the
|
# re-raise the NoReverseMatch unless we're using the
|
||||||
# {% url ... as var %} construct in which cause return nothing.
|
# {% url ... as var %} construct in which cause return nothing.
|
||||||
url = ''
|
url = ''
|
||||||
try:
|
try:
|
||||||
|
@ -388,7 +378,7 @@ class URLNode(Node):
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
if self.asvar is None:
|
if self.asvar is None:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if self.asvar:
|
if self.asvar:
|
||||||
context[self.asvar] = url
|
context[self.asvar] = url
|
||||||
return ''
|
return ''
|
||||||
|
@ -514,12 +504,14 @@ def cycle(parser, token):
|
||||||
|
|
||||||
if len(args) > 4 and args[-2] == 'as':
|
if len(args) > 4 and args[-2] == 'as':
|
||||||
name = args[-1]
|
name = args[-1]
|
||||||
node = CycleNode(args[1:-2], name)
|
values = [parser.compile_filter(arg) for arg in args[1:-2]]
|
||||||
|
node = CycleNode(values, name)
|
||||||
if not hasattr(parser, '_namedCycleNodes'):
|
if not hasattr(parser, '_namedCycleNodes'):
|
||||||
parser._namedCycleNodes = {}
|
parser._namedCycleNodes = {}
|
||||||
parser._namedCycleNodes[name] = node
|
parser._namedCycleNodes[name] = node
|
||||||
else:
|
else:
|
||||||
node = CycleNode(args[1:])
|
values = [parser.compile_filter(arg) for arg in args[1:]]
|
||||||
|
node = CycleNode(values)
|
||||||
return node
|
return node
|
||||||
cycle = register.tag(cycle)
|
cycle = register.tag(cycle)
|
||||||
|
|
||||||
|
@ -594,7 +586,7 @@ def firstof(parser, token):
|
||||||
if len(bits) < 1:
|
if len(bits) < 1:
|
||||||
raise TemplateSyntaxError("'firstof' statement requires at least one"
|
raise TemplateSyntaxError("'firstof' statement requires at least one"
|
||||||
" argument")
|
" argument")
|
||||||
return FirstOfNode(bits)
|
return FirstOfNode([parser.compile_filter(bit) for bit in bits])
|
||||||
firstof = register.tag(firstof)
|
firstof = register.tag(firstof)
|
||||||
|
|
||||||
#@register.tag(name="for")
|
#@register.tag(name="for")
|
||||||
|
@ -629,10 +621,10 @@ def do_for(parser, token):
|
||||||
<li>Sorry, no athletes in this list.</li>
|
<li>Sorry, no athletes in this list.</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
The above is equivalent to -- but shorter, cleaner, and possibly faster
|
The above is equivalent to -- but shorter, cleaner, and possibly faster
|
||||||
than -- the following::
|
than -- the following::
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% if althete_list %}
|
{% if althete_list %}
|
||||||
{% for athlete in athlete_list %}
|
{% for athlete in athlete_list %}
|
||||||
|
@ -701,7 +693,9 @@ def do_ifequal(parser, token, negate):
|
||||||
parser.delete_first_token()
|
parser.delete_first_token()
|
||||||
else:
|
else:
|
||||||
nodelist_false = NodeList()
|
nodelist_false = NodeList()
|
||||||
return IfEqualNode(bits[1], bits[2], nodelist_true, nodelist_false, negate)
|
val1 = parser.compile_filter(bits[1])
|
||||||
|
val2 = parser.compile_filter(bits[2])
|
||||||
|
return IfEqualNode(val1, val2, nodelist_true, nodelist_false, negate)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifequal(parser, token):
|
def ifequal(parser, token):
|
||||||
|
@ -864,7 +858,8 @@ def ifchanged(parser, token):
|
||||||
parser.delete_first_token()
|
parser.delete_first_token()
|
||||||
else:
|
else:
|
||||||
nodelist_false = NodeList()
|
nodelist_false = NodeList()
|
||||||
return IfChangedNode(nodelist_true, nodelist_false, *bits[1:])
|
values = [parser.compile_filter(bit) for bit in bits[1:]]
|
||||||
|
return IfChangedNode(nodelist_true, nodelist_false, *values)
|
||||||
ifchanged = register.tag(ifchanged)
|
ifchanged = register.tag(ifchanged)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
|
@ -1105,7 +1100,7 @@ def url(parser, token):
|
||||||
args = []
|
args = []
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
asvar = None
|
asvar = None
|
||||||
|
|
||||||
if len(bits) > 2:
|
if len(bits) > 2:
|
||||||
bits = iter(bits[2:])
|
bits = iter(bits[2:])
|
||||||
for bit in bits:
|
for bit in bits:
|
||||||
|
|
|
@ -424,13 +424,13 @@ class Templates(unittest.TestCase):
|
||||||
'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
|
'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
|
||||||
'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
|
'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
|
||||||
'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||||
# New format:
|
|
||||||
'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
|
'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
|
||||||
'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
|
'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
|
||||||
'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
|
'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
|
||||||
'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||||
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
|
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
|
||||||
'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
|
'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
|
||||||
|
'cycle16': ("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'),
|
||||||
|
|
||||||
### EXCEPTIONS ############################################################
|
### EXCEPTIONS ############################################################
|
||||||
|
|
||||||
|
@ -638,6 +638,13 @@ class Templates(unittest.TestCase):
|
||||||
'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),
|
'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),
|
||||||
'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
|
'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
|
||||||
|
|
||||||
|
# FILTER EXPRESSIONS AS ARGUMENTS
|
||||||
|
'ifequal-filter01': ('{% ifequal a|upper "A" %}x{% endifequal %}', {'a': 'a'}, 'x'),
|
||||||
|
'ifequal-filter02': ('{% ifequal "A" a|upper %}x{% endifequal %}', {'a': 'a'}, 'x'),
|
||||||
|
'ifequal-filter03': ('{% ifequal a|upper b|upper %}x{% endifequal %}', {'a': 'x', 'b': 'X'}, 'x'),
|
||||||
|
'ifequal-filter04': ('{% ifequal x|slice:"1" "a" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
|
||||||
|
'ifequal-filter05': ('{% ifequal x|slice:"1"|upper "A" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),
|
||||||
|
|
||||||
### IFNOTEQUAL TAG ########################################################
|
### IFNOTEQUAL TAG ########################################################
|
||||||
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
||||||
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
||||||
|
|
Loading…
Reference in New Issue