Recently, I discovered something surprising about Google App Engine’s datastore and ReferenceProperty. Imagine I have a class like the following:


  from google.appengine.ext import db
  class Home(db.Model):
    address = db.StringProperty()
    room = db.ReferenceProperty(Room)

where Room is also a db.Model.

Datastore uses a proxying technique such that db.Model objects are created lightly (i.e., with only their key) and any hit to an attribute causes the entire object to be inflated by looking it up in the datastore.

I thought this was achieved with a lazy load technique, meaning that Room in the above example contained the logic to load itself (or more accurately Home would populate room with a proxy to Room that would know how to inflate). To do this, the proxy class would hold only its key and use that key to look itself up. From this, it follows that I could access that key without inflating the object.

It doesn’t work this way!

Instead, the referencing class (Home in the above example) holds the key (in a protected attribute, which you shouldn’t touch) and is responsible for inflating reference types.

I’ll say that again: the referenced object does not inflate itself lazily, but the referencing object does the inflation.

So, I previously thought code like this would not cause a datastore lookup:


  # assume home is an instance of Home
  room_key = home.room.key()

but I was very wrong. Simply hitting home.room causes home to lookup the entire room.

But what if you only want to get at the key (which the home has, but is protecting)?

This post suggests that the safe way to get this key is to access it via the class attribute, not the instance attribute. Here is the resulting code for my example:


  room_key = Home.room.get_value_for_datastore(home)

Note carefully the capitalization (indicating the classes versus objects).

This gives me the room key without causing a room lookup. Over and out.



2 Responses to “Retrieving the key from a ReferenceProperty in Google App Engine”  

  1. The unsafe way that you are implicitely referring to would be using

    home._room

    I suppose?

    • 2 Jason Collins

      Yes. By unsafe, I only mean that, since _room is not part of the public interface, G may make changes someday that break your code.


Leave a Reply