Method Invocation Behavior
Method calls are slightly more complex than other types of lookups. Here are some caveats:
During method lookup, if a method throws an exception, it will be propagated unless the exception has a silent_variable_failure attribute with a value of True. If the exception is propagated, the specified variable in the template is set to the empty string, e.g..
>>> t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: ... def first_name(self): ... raise AssertionError, "foo" >>> p = PersonClass3() >>> (Context({"person": p})) Traceback (most recent call last): ... AssertionError: foo >>> class SilentAssertionError(AssertionError): ... silent_variable_failure = True >>> class PersonClass4: ... def first_name(self): ... raise SilentAssertionError >>> p = PersonClass4() >>> (Context({"person": p})) u'My name is .'
Methods are only valid to call if they don't need to be passed parameters. Otherwise, the system will move to the next lookup type (list index lookup).
Obviously, some of these methods have side effects; in good cases allowing the template system to access them might just be doing something stupid, and in bad cases it might even trigger a security breach.
For example, one of your BankAccount objects has a delete() method. If a template contains tags like {{ }} where ``account`` is an instance of BankAccount, note that the account object will be deleted when this template is loaded.
To prevent this from happening, you must set the alters_data function property of the method:
def delete(self): # Delete the account delete.alters_data = True
The template system does not execute any methods that are marked in that way. To pick up on the above example, if the template file contains {{ }} and the object has a delete() method and delete() has the attribute alters_data=True, the delete() method will not be executed when the template is loaded. It will exit silently with an error.
How to handle invalid variables
By default, if a variable does not exist, the template system displays it as an empty string and does nothing to indicate failure. Example:
>>> from import Template, Context >>> t = Template('Your name is {{ name }}.') >>> (Context()) u'Your name is .' >>> (Context({'var': 'hello'})) u'Your name is .' >>> (Context({'NAME': 'hello'})) u'Your name is .' >>> (Context({'Name': 'hello'})) u'Your name is .'
The system quietly indicates failure rather than raising an exception, as this is usually the result of human error. In this case, because the variable name has the wrong status or name, all queries will fail. In the real world, it would be unacceptable for a web site to become inaccessible just because of a minor template syntax error.