views:

176

answers:

1

Assume I have a Model class called Bird and a instance of Bird called pigeon. I know I can get all the Properties of Pigeon (or bird) using

properties = pigeon.properties() #Note, Bird.properties() would also work

This returns me a dictionary where the keys are strings that match the name I gave said properties in birds, and the value are actual Property objects. My question is, how do I get or set the value using said property objects. I wish to do this because I want to allow a client to dynamically specify as strings:

1) the key to a Model object

2) a property of said Model object

3) and a value that the afformentioned Property of said Model object might take on

So clearly, I need to first get the Model object, then determine whether said Property exist, and finally get or set it somehow? Is this possible? Thank you.

+2  A: 

I played around with App Engine Console, which is great for testing and experimenting. It looks to me like you want to use __set__, with the first argument being your model instance, and the second being the new value. Next you need to put() the instance as usual.

Here is the console session to make it clearer. (Have I mentioned how App Engine Console is awesome?)

>>> from google.appengine.ext import db
>>> class Bird(db.Model):
...   name = db.StringProperty()
...   can_fly = db.BooleanProperty()
... 
>>> def summarize():
...   for name in ('Pesto', 'Bobby'):
...     count = Bird.all().filter('name =', name).count()
...     print 'I found %d birds named %s' % (count, name)
...
>>> summarize()
I found 0 birds named Pesto
I found 0 birds named Bobby
>>> pigeon = Bird(name='Pesto', can_fly=True)
>>> pigeon.put()
datastore_types.Key.from_path('Bird', 41015L, _app=u'con')
>>> summarize()
I found 1 birds named Pesto
I found 0 birds named Bobby
>>> props = pigeon.properties()
>>> props
{'can_fly': <google.appengine.ext.db.BooleanProperty object at 0x46ddd1cc3ddb2268>, 'name': <google.appengine.ext.db.StringProperty object at 0x46ddd1cc3ddb2fe8>}
>>> prop = props['name']
>>> prop
<google.appengine.ext.db.StringProperty object at 0x46ddd1cc3ddb2a68>
>>> prop.__set__(pigeon, 'Bobby')
>>> pigeon.name
'Bobby'
>>> pigeon.put()
datastore_types.Key.from_path('Bird', 41015L, _app=u'con')
>>> summarize()
I found 0 birds named Pesto
I found 1 birds named Bobby
>>> bobby = Bird.all().filter('name =', 'Bobby').fetch(1)[0]
>>> bobby.name
u'Bobby'

If you try the online console demo yourself, be sure to delete my old instances first, as we all share the same data store.

jhs
This is exactly right. For more details on why it works like this, check out Raymond Hettinger's excellent "How to guide for descriptors": http://users.rcn.com/python/download/Descriptor.htm
Nick Johnson