I am getting: argument of type 'Lantern' is not iterable in one of the template engine files (Cheetah). As you can guess the obj is a Lantern (see below).
NameWrapper.py:
if hasattr(obj, 'has_key') and key in obj:
This is a simplified version of my models. Nothing fancy, no additional methods just attribute declarations.
models.py:
from google.appengine.ext import db
class Product(db.Model):
name = db.StringProperty(required=True)
class Lantern(Product):
height = db.IntegerProperty()
Solution(edit):
I have replaced the line.
if hasattr(obj, 'has_key') and isinstance(obj, collections.Iterable) and key in obj:
The NameMapper
implementation makes the erroneous assumption that having a has_key()
method makes the Model
class a mapping and tries to test for key membership.
This is a bug in the Cheetah NameMapper
implementation and should be reported to the project. You could try to disable the NameMapper
functionality, the documentation suggests it is optional and can be switched of with the useNameMapper
compiler setting. I'm not familiar with the syntax, but try to avoid relying on the functionality in your templates.
If you are not averse to editing the Cheetah code, you could replace the tests with:
from collections import Mapping
if isinstance(obj, Mapping) and key in obj:
which uses the correct Abstract Base Class to detect a mapping object.
Model
objects are not mappings. The Model.has_key()
function does not test for the presence of a mapping key, it is a method that tests if the object has a datastore key.
The documentation string on the method is:
def has_key(self):
"""Determine if this model instance has a complete key.
When not using a fully self-assigned Key, ids are not assigned until the
data is saved to the Datastore, but instances with a key name always have
a full key.
Returns:
True if the object has been persisted to the datastore or has a key
or has a key_name, otherwise False.
"""
Note that the above method does not take an argument, apart from the automatically-bound self
.
Model.has_key()
appears to be a convenience method that Google didn't include in the Model Class documentation; it'll return False
when the Model.key()
method would throw the NotSavedError
exception instead.
In any case, Model
objects are not sequences; they have no __iter__
method, nor do they have a length or support indexing. As such they are not iterable. Having an has_key()
method does not imply that they should be.