webpy/webpy — Issue #134: Error occurs when you try to fill a webpy form with a GAE db.Model dataobject.
Author: bkiessli
Created: 2012-01-30 12:10:39+00:00
State: open

The reason for this is that webpy.form and GAE db.Model both use the method "has_key" in a different context, and with different signatures. This should fixed in the release. A temporary workaround and a final buxfix are provided below.

Error description:

form.fill(todo)

File "C:\Users\bkiessli\Dropbox\Data\webpy\gaetodoliste\web\form.py", line 88, in fill
return self.validates(source, _validate=False, **kw)
File "C:\Users\bkiessli\Dropbox\Data\webpy\gaetodoliste\web\form.py", line 69, in validates
v = attrget(source, i.name)
File "C:\Users\bkiessli\Dropbox\Data\webpy\gaetodoliste\web\form.py", line 11, in attrget
if hasattr(obj, 'has_key') and obj.has_key(attr): return obj[attr]
TypeError: has_key() takes exactly 1 argument (2 given)

Example Code definiton:

def GET(self, schluessel):
todo = model.get_todo(schluessel)
form = NeueAufgabe.form()
form.fill(todo)	# <<<< trouble occurs here
return render.edit(form)

class TodoListe (db.Model):
titel = db.StringProperty(multiline=False)
beschreibung = db.StringProperty(multiline=True)

Workaround:

Override and extend the GAE db.Model class and use it instead

class GAEwebpyModel (db.Model):
"""
Workaround for web.form bug when filling a form with db.Model object
"""
def __getitem__(self, item):
"""
Giving access to GAE db.Models data fields
"""
return getattr(self,item)

def has_key (self, attribute=None):
"""
Extending a second argument
"""
if attribute == None:
super.hash_key()
else:
if hasattr(self,attribute):
return True
else:
return False

class TodoListe (GAEwebpyModel):
titel = db.StringProperty(multiline=False)
beschreibung = db.StringProperty(multiline=True)

Bugfix that should be implemented by fixing defect in webpy.form:

def attrget(obj, attr, value=None):
try:
if hasattr(obj, 'has_key') and obj.has_key(attr): return obj[attr]
except :
if hasattr(obj, attr): return getattr(obj, attr)
return value