Using non-Model mix-ins worked a treat. Thanks again Rafe.

There is one small problem I'm hoping you can help me with (again). It's not
a show-stopper because I can work around it, however I'm hoping you'd know
of a nicer way to do this. Note that it's not only specific to PolyModel,
but to db.Model as well.

The problem is with adding extra db.* properties to these mix-ins (so that
all subclasses that use the mix-in get these extra properties stored in the
Datastore).

Let's say I change the CoolFeature mix-in to this:

class CoolFeature(object):

*  cool_name = db.StringProperty()*

  def put(self):
    self.cool_name = 'Cool ' + self.name
    super(CoolFeature, self).put()

class MyModel(CoolFeature,db.Model):

  name = db.StringProperty()

If I then create an instance of MyModel and try put()'ing it to the
Datastore:

mm = MyModel(name='blah')
mm.put()

I get this error:

Traceback (most recent call last):
  ...
  File
"/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py",
line 473, in __set__
    setattr(model_instance, self._attr_name(), value)
  File
"/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py",
line 588, in _attr_name
    return '_' + self.name
TypeError: cannot concatenate 'str' and 'NoneType' objects

This error occurs both on the dev and production servers.

Upon further investigation, the error occurs because the name property of
the underlying Property superclass of the cool_name property instance is
None. So I then changed the bold line above to:

  cool_name = db.StringProperty(name='cool_name')

This got rid of the error being raised, however the cool_name property was
not saved to the Datastore (only the name property was).

The workaround is to add the property cool_name to each
CoolFeaturesubclass. So it's not terribly bad, but if you know of a
better way to
accomplish what I'm trying to do, I'd love to hear it.

Cheers,

Nick


On 5 March 2010 12:40, Nickolas Daskalou <[email protected]> wrote:

> Thanks for your reply Rafe. Using non-Model mix-ins seems like the way to
> go.
>
> As with many App Engine developers, my Python experience is equivalent to
> my App Engine experience, so I appreciated the Python lesson ;)
>
> Nick
>
>
> On 5 March 2010 08:52, Rafe <[email protected]> wrote:
>
>>  There is currently no proper way to do "re-root" a polymodel the way
>> you are describing.  However, there may be a solution for your
>> particular problem.  I don't know enough about your actual
>> implementation however you might get away with simply doing a non-
>> Model based mix-in.  So, write your memcache utility class AS IF it
>> inherits from PolyModel, but don't actually allow it to do so.  Like
>> this:
>>
>>    class CoolFeature(object):
>>
>>      def put(self):
>>        ... clear memcache ...
>>        super(CoolFeature, self).put()
>>
>>  Now define your root class:
>>
>>    class MyModel(CoolFeature, polymodel.PolyModel):
>>      ...
>>
>>  Here comes the Python lesson, so forgive me if you already know all
>> this ;)
>>
>>  The key is that you use 'super' correctly and that you have
>> CoolFeature be the first class your model class inherits from.
>> 'super' allows you to traverse your objects functionality correctly
>> according to the python "method resolution order".  You can see this
>> order by for any class by studying MyModel.__mro__.  This indicates
>> the order which calls to super will traverse your class definitions.
>> If you do:
>>
>> class A(object):
>>
>>  def p(self):
>>    print 'A'
>>
>>
>> class B(object):
>>
>>  def p(self):
>>    print 'B'
>>    super(B, self).p()
>>
>>
>> class C(B, A):
>>
>>  def p(self):
>>    print 'C'
>>    super(C, self).p()
>>
>> ...calling C().p() will print:
>>
>>  C
>>  B
>>  A
>>
>>  You should be able to implement whatever functionality you need this
>> way.  Let me know if there are issues with doing that.
>>
>>
>> On Mar 3, 7:40 pm, Nickolas Daskalou <[email protected]> wrote:
>> > I should state that I can set the entity kind that's saved in the
>> > Datastore by adding a kind() method on my "real" models, however the
>> > class list property of the saved entities still includes the "special"
>> > PolyModel subclass in it, and I'm not sure if that's a bad thing or
>> > not.
>> >
>> > On Mar 4, 2:16 pm, Nickolas Daskalou <[email protected]> wrote:
>> >
>> > > I've been trying to create a "special" subclass of PolyModel (that
>> does cool
>> > > stuff like update Memcache after an entity put()) which my polymodel
>> models
>> > > can inherit from (instead of inheriting from db.polymodel.PolyModel).
>> >
>> > > This has the nasty side effect though of making that  "special"
>> subclass of
>> > > PolyModel the root class for my polymodel models.
>> >
>> > > Is there a way around this?
>> >
>> > > Eg. Telling db.polymodel.PolyModel to NOT include the first direct
>> subclass
>> > > in the class hierarchy that is saved to the Datastore? Or writing my
>> own
>> > > PolyModel by basically copying db.polymodel and changing code where
>> > > appropriate?
>> >
>> > > Appreciate any help.
>> >
>> > > Nick
>>
>> --
>> 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]<google-appengine%[email protected]>
>> .
>> For more options, visit this group at
>> http://groups.google.com/group/google-appengine?hl=en.
>>
>>
>

-- 
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