In this scenario, company.py contains:
from django.utils import simplejson
class Company(db.Model):
name=db.StringProperty()
address=db.StringProperty()
def to_JSON():
d = dict([(p, unicode(getattr(self, p))) for p in self.properties()])
return simplejson.dumps(d)
office.py contains:
from company import Company
class Office(db.Model):
name = db.StringProperty()
company = db.ReferenceProperty(Company, collection_name='offices')
module 3 contains:
from company import Company
class Region(db.Model):
name = db.StringProperty()
company = db.ReferenceProperty(Company, collection_name='regions')
This is a simplified example of what I need to do, but should capture it pretty well... I need Company to be able to express itself as a JSON string, and it does not know about the other classes (Office and Region) that reference it. This works for the normal properties:
c = Company(name='A Company',address='123 Main St, New York, NY 12345')
c.put()
dallas = Office(name='Dallas',company=c)
dallas.put()
ny = Office(name='New York',company=c)
ny.put()
northeast = Region(name='NorthEast',company=c)
northeast.put()
southwest = Region(name='SouthWest',company=c)
southwest.put()
logging.info('Company as JSON: %s' % c.to_JSON())
And what I get for output is:
{"name": "A Company", "address": "123 Main St, New York, NY 12345"}
So properties() includes the properties of the entity as expected, but I also want to include the back-references from the ReferenceProperty attributes of the associated objects. Essentially what I'm looking for is just a list of the back-reference (collection_name) names, since I know they represent queries, but I can't find any way to enumerate the back-reference names themselves.
Remember this code isn't actually indicative of the real code, it's greatly simplified. Now this works:
offices = getattr(company, 'offices')
So what I was expecting to see was this:
{"name": "A Company", "address": "123 Main St, New York, NY 12345",
"offices": "<db.Query object at 0x110e992d0>",
"regions": "<db.Query object at 0x110e99300>"
}
I don't actually need the back-references "offices" and "regions" to be included in the properties() enumerations, but they're checked for uniqueness somehow (I couldn't, for example, also have a StringProperty in Company named 'offices') so there must be a way to enumerate them. Anyone know of a way?
The check for uniqueness is simply against the class dict (that is, the internal object that provides a mapping between names and values for the class object). You can iterate over these by examining Company.__dict__
. This includes everything, though - all the properties, attributes and methods of the built in Python object
, likewise for db.Model
and any other parent classes.
Your best option would be to iterate over the class dict, checking each item to see if it's an instance of _ReverseReferenceProperty
:
for propname, prop in Company.__dict__.iteritems():
if isinstance(prop, db._ReverseReferenceProperty):
# Do something with prop, such as getting a query with getattr(a_company, propname).