I was able to answer my own question after about an hour of
experimenting and diving into the GAE code base.  The solution that I
found is a bit of hack, and it is dependent on the internals of some
of the Model support classes, so it could be broken in a future
release, but it'll suffice for the time being.  I'd love to hear from
an AppEngine Engineer about the validity of this approach and any
possible alternatives.

So, to quickly recap the problem: I'd like to write a mixin class, in
the style of taggable-mixin, that would make Model class Commentable.
The Commentable class would add a field, comment_count, the the Model
class that is mixing it in.  I tried having Commentable inherit from
db.Model, just as Post did, but that caused a variety of problems.  As
is, while the comments_counter attribute was added to the Post object,
it was not interacting with the datastore.

class Commentable:
    comments_counter = db.IntegerProperty(required=True, default=0)

    # Various method definitions excluded for brevity...

class Post(db.Model, Commentable):
    title = db.StringProperty(required=True)
    body = db.TextProperty(required=True)
    added = db.DateProperty(auto_add_now=True)
    # comments_counter = db.IntegerProperty(required=True, defualt=0)
    # Now, comments_counter is included by Commentable mixin

The missing bit of magic is this:

class Commentable:
    comments_counter = db.IntegerProperty(required=True, default=0)
    _properties = {"comment_count" : comment_count}

Why does it work?  Well, db.Model has a metaclass, PropertiedClass,
that iterates over all of the properties in a Model class, and if the
property is a database Property, it puts a reference to the property
in a dictionary called _properties, and everything in there interacts
with the datastore.  It also looks at all of the Model class's base
classes, and copies in the contents of their _properties dictionary.
it looks as though this is explicity to provide support for
inheritance, so I'm surprised that I can't just have Commentable
inherit from db.Model.  Perhaps that is a bug; I'll have to look in to
it further when I have time.

In the mean time, that problem can be circumvented just by explicitly
adding a _properties dictionary and adding that desired model field to
it.  That gets picked up by the metaclass and the magic happens.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to