2

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?

Timothy Tripp
  • 3,277
  • 1
  • 14
  • 8

2 Answers2

1

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).
Nick Johnson
  • 100,655
  • 16
  • 128
  • 198
0

Let's suppose you don't assign values to collection_name, just leave it as Modelname_set. Then you can dir(model), choose the attributes ending in _set, and those are the backreferences. Or you can make a convention to name them eg. groups_refs, and search for attributes ending in _refs.

Adam Wagner
  • 15,469
  • 7
  • 52
  • 66
Egon
  • 1