I have this "funny" issue. I know this error message is found in a lot of places, but I couldn't find one explicitely related to Mako.
In a Mako template, I have (snippet):
<%inherit file="other.mako"/>
<%def name="my_method()">Search for ${label}</%def>
[...]
<h2>${label.capitalize()} found: ${len(l)}</h2>
...
<ol>
% for (label, field_name) in some_list:
<li>${label}: ${field_name}</li>
% endfor
</ol>
and I would get the error:
UnboundLocalError: local variable 'label' referenced before assignment
The weird part is that if I just don't use the second ${label.capitalize()}
, I don't get any error, and the value of ${label}
in the <%def>
is the one I want, not the one from the for-loop. If I had the same error with the variable in <%def>
, it may be clear to not reuse the same variable name, but in this case, I'm quite puzzled that such thing happens.
Can anyone tell me how I can avoid this beside renaming the variable label in the for-loop? If I rename the for-loop variable name, the problem disappear. I am transferring from another templating system that did not have this sort of error, so this similar scenario happens quite often.
Thanks for any pointers,
D.
EDIT for clarity:
I am calling my template using:
renderers.render_to_response(my_mako_tmpl,
{'label': 'value', 'somelist':[a,b,c], 'l':[]},
request=request)
My question is: Why the fact that I have the % for (label, field_name)
-loop, the variable label
is giving me and error in ${label.capitalize()}
, where as it does not give me any error for Search for ${label}
.
If I change my for-loop for:
% for (label_name, field_name) in some_list:
I get no error.
If I don't change the for-loop, but I change:
<h2>${label.capitalize()} found: ${len(l)}</h2>
to
<h2>Items found: ${len(l)}</h2>
I get no error even if ${label}
is used in my <%def>
.
Also, to add info for the template usage, I added the <%inherit>
and here is how the other.mako
is defined (snippet):
<%def name="my_method()">Default value</%def>
Value of my_method() = ${self.my_method()}
So I don't need to pass any value to my_method()
.
Hope this make the question more clear.
It is best to think of a Mako template as being similar to a piece of python code. Thus, as in python, you will have issues if you expect a variable to take on both local scope and global (or nested scope).
Thinking of a template as a function that takes variables, and defines within it various other functions including a body()
function, then your problem is effectively similar to the following
>>> def f(x):
... def body():
... print x
... for x in range(5):
... print x
... body()
...
>>> f(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in f
File "<stdin>", line 3, in body
UnboundLocalError: local variable 'x' referenced before assignment
You shouldn't expect this to work in Python, and similarly, you shouldn't expect it to work in a Mako template.