views:

28

answers:

1

If I have the following models in a Python (+ Django) App Engine app:

class Album(db.Model):
  private = db.BooleanProperty()
  ...

class Photo(db.Model):
  album = db.ReferenceProperty(Album)
  title = db.StringProperty()

...how can I retrieve all Photos that belong to a public Album (that is, an Album with private == False)?

To further explain my intention, I thought it would be:

public_photos = Photos.all().filter('album.private = ', False)

and then I could do something like:

photos_for_homepage = public_photos.fetch(30)

but the query does not match anything, which tells me I'm going down the wrong path.

+4  A: 

You can't. App engine doesn't support joins.

One approach is to implement the join manually. For example you could fetch all photos, then filter out the private ones in code. Or fetch all public albums, and then fetch each of their photos. It depends on your data as to whether this will perform okay or not.

The alternative approach is to denormalize your data. Put another field in the Photo model, eg:

class Photo(db.Model): 
  album = db.ReferenceProperty(Album) 
  album_private = db.BooleanProperty()
  title = db.StringProperty() 

Then you can filter for public photos with:

public_photos = Photos.all().filter('album_private = ', False)

This improves query performance, but at the expense of write performance. You will need to keep the album_private field of the photos updated whenever you change the private flag of the album. It depends on your data and read/write patterns as to whether this will be better or worse.

Saxon Druce
Thanks very much for the thoughtful reply - I've implemented the alternative approach, just have to be careful to keep album_private updated!
bfox