Lost in LoC


Google AppEngine PolyModels and ModelForms

Posted in Development,Technology by Ryan Baldwin on April 11, 2009
Tags: , , ,

I recently created my first PolyModel class in Google AppEngine for a new feature. The feature was pretty straight forward  - allow comments for some of the entities in our application Homebook.  We wanted each comment to be tied back to its target entity – a room, house, or image – in a 1-to-many (each entity can have many comments). Using PolyModel we found this to be pretty easy without duplicating a bunch of code.  Essentially the structure of Comment class hierarchy looked like the following:

class Comment(PolyModel):
    # bunch of common fields

class RoomComment(Comment):
    target = db.ReferenceProperty(reference_class=Room, collection_name=’comments’)

class HomeComment(Comment):
    target = db.ReferenceProperty(reference_class=Home, collection_name=’comments’)

class ImageComment(Comment):
    target = db.ReferenceProperty(reference_class=Image, collection_name=’comments’)

Really straight forward – simple class inheritance. I then created a simple factory method that would fetch the proper class type for a given instance of one of our commentable entities. Things were moving along nicely (complete with lots of beautiful unit tests – you do write unit tests, right?) and it was time to create the add_comment view.

For the most part we use Google AppEngine’s djangoforms ModelForms, a theoretically clean and easy way to create web forms based on data models. I created my standard ModelForm class (based on our parent Comment class) and the view against which the form would post, only to be blindsided by the oddest of validation errors:

  • _class
    • This field is required.

Huh? _class? What gives? Well, after a couple hours of soul searching, googling (which turned up nothing), and a few tears, my genius coworker Tony Arkles had an epiphany: The PolyModel class has a _class field which is used to keep track of the PolyModel instance’s class hierarchy. We added the _class field to our form’s exclude list and the world righted itself, cats and dogs learned to coexist, and Liz Taylor finally discovered a happy marriage.

Now the question is, why is the ModelForm rendering a field that’s not a google.appengine.ext.db model property? Can anybody from Google answer me that?

One Response to 'Google AppEngine PolyModels and ModelForms'

Subscribe to comments with RSS or TrackBack to 'Google AppEngine PolyModels and ModelForms'.

  1. Tony Arkles said,

    I’m out of town right now, so I can’t verify this. I’m going to guess that Google’s not the guilty party here; rather, it sounds like either a problem with the app-engine-patch/app-engine-helper/whatever you guys are using now, or a problem in the ModelForms implementation.

    (On first blush, I’d say that the ModelForms implementation has no business accessing any “_private” members)


Leave a Reply