Hi Nick, I have been using the pattern described by Rafe very successfully in my app. Regarding the problem you are desribing I have written up how I solved the problem here:
http://www.gae123.com/articles/tds/model-mixin.html Read the whole page for the details or just scroll to the bottom for the solution that has worked for me. PK http://www.gae123.com On Mar 4, 10:22 pm, Nickolas Daskalou <[email protected]> wrote: > 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.- Hide quoted text - > > - Show quoted text - -- 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.
