google app engine - Idiomatic List Wrapper -
in google app engine, make lists of referenced properties this:
class referenced(basemodel): name = db.stringproperty() class thing(basemodel): foo_keys = db.listproperty(db.key) def __getattr__(self, attrname): if attrname == 'foos': return referenced.get(self.foo_keys) else: return basemodel.__getattr__(self, attrname)
this way, can have thing
, thing.foos
, legitimate out of it. problem comes when says thing.foos.append(x)
. not save added property because underlying list of keys remains unchanged. wrote solution make easy append keys list:
class keybackedlist(list): def __init__(self, key_class, key_list): list.__init__(self, key_class.get(key_list)) self.key_class = key_class self.key_list = key_list def append(self, value): self.key_list.append(value.key()) list.append(self, value) class thing(basemodel): foo_keys = db.listproperty(db.key) def __getattr__(self, attrname): if attrname == 'foos': return keybackedlist(thing, self.foo_keys) else: return basemodel.__getattr__(self, attrname)
this great proof-of-concept, in works expected when calling append
. however, never give other people, since might mutate list in other ways (thing[1:9] = whatevs
or thing.sort()
). sure, go define __setslice__
, whatnot, seems leave me open obnoxious bugs. however, best solution can come with.
is there better way trying (something in python library perhaps)? or going wrong way , trying make things smooth?
if want modify things this, shouldn't changing __getattr__
on model; instead, should write custom property class.
as you've observed, though, creating workable 'referencelistproperty' difficult , involved, , there many subtle edge cases. recommend sticking list of keys, , fetching referenced entities in code when needed.
Comments
Post a Comment