Using parent = or ancestor is probably faster because the locality of
datastore.

On Oct 13, 4:30 am, djidjadji <[EMAIL PROTECTED]> wrote:
> Hello,
>
> I'm looking for a way to store and retrieve a polymorphic one-to-many 
> relation.
> The test case I used is for a drawing on a page to contain different
> shapes (lines,circles,...).
>
> In my first attempt I used a ReferenceProperty in the Shape class to
> the Page class. (see code section 1)
> The objects (lines,circle) are stored correctly with all the
> attributes, but the Page object can't retrieve
> the shapes it contains probably because the shapes-Query looks something like
> "SELECT * FROM Shape WHERE onPage=:1", page
> and there is no Shape instance, only Line and Circle instances that
> have the correct onPage attribute.
>
> My second attempt is to use a ListProperty(db.Key) in the Page class,
> like suggested for the
> many-many relations. (see code section 2).
> Now the creation of the shapes with a classmethod, extra put for every
> shape created.
> The output I get is correct. The Page draws the shapes it contains.
> -------------------
> Page: Number1
>         Line (0,0)-(10,5) in red
>         Line (10,5)-(5,-10) in orange
>
> Page: Number2
>         Line (0,0)-(1,5) in black
>         Circle (0,0)r3 in green
> -------------------
>
> The question I have is, is this the most efficient method to store
> this from a datastore point of view?
> Is there a problem when the ListProperty(db.Key) has a lot of items?
> What number of items is no problem for a ListProperty?
> Will it have a big impact in retrieving a Page instance when it has a
> lot of 'shapes'/db.Key's in the list?
>
> djidjadji
>
> ------------------------------------------------- code section 1 BEGIN
> --------------------------------------------------------------------------- 
> -----
> import cgi
> import os
>
> from google.appengine.ext.webapp import template
> from google.appengine.ext import db
> from google.appengine.ext import webapp
> from google.appengine.ext.webapp.util import run_wsgi_app
>
> class Page(db.Model):
>   name = db.StringProperty(required=True)
>   def draw(self):
>     drawing = '\n'.join(['\t'+s.draw() for s in self.shapes.fetch(1000)])
>     return 'Page: %s\n%s\n' % (self.name,drawing)
>
> class Shape(db.Model):
>   onPage = db.ReferenceProperty(Page,collection_name="shapes",required=True)
>   color  = db.StringProperty(required=True,default='black')
>   def draw(self):
>     return ''
>
> class Line(Shape):
>   startX = db.IntegerProperty(default=0)
>   startY = db.IntegerProperty(default=0)
>   endX = db.IntegerProperty(default=0)
>   endY = db.IntegerProperty(default=0)
>   def draw(self):
>     return 'Line (%d,%d)-(%d,%d) in %s' % (
>       self.startX,self.startY,self.endX,self.endY,self.color)
>
> class Circle(Shape):
>   centerX = db.IntegerProperty(default=0)
>   centerY = db.IntegerProperty(default=0)
>   radius  = db.IntegerProperty(default=1)
>   def draw(self):
>     return 'Circle (%d,%d)r%d in %s' % (
>       self.centerX,self.centerY,self.radius,self.color)
>
> class MainPage(webapp.RequestHandler):
>   def get(self):
>     pages = '\n'.join([p.draw() for p in Page.all().fetch(1000)])
>     self.response.headers['Content-Type'] = 'text/plain'
>     self.response.out.write(pages)
>
> class Create(webapp.RequestHandler):
>   def get(self):
>     page = Page(name='Number1')
>     page.put()
>     line = Line(onPage=page,endX=10,endY=5,color='red')
>     line.put()
>     line = Line(onPage=page,startX=10,startY=5,endX=5,endY=-10,color='orange')
>     line.put()
>     page = Page(name='Number2')
>     page.put()
>     line = Line(onPage=page,endX=1,endY=5)
>     line.put()
>     circle = Circle(onPage=page,startX=5,startY=0,radius=3,color='green')
>     circle.put()
>     self.redirect('/')
>
> application = webapp.WSGIApplication(
>       [('/', MainPage),
>        ('/create', Create),
>       ],
>       debug=False)
>
> def main():
>   run_wsgi_app(application)
>
> if __name__ == "__main__":
>   main()
> ------------------------------------------------- code section 1 END
> --------------------------------------------------------------------------- 
> --------
>
> ------------------------------------------------- code section 2 BEGIN
> ---- Changed methods -----------------------------------------------
> class Page(db.Model):
>   name = db.StringProperty(required=True)
>   shapes = db.ListProperty(db.Key)
>   def draw(self):
>     drawing = '\n'.join(['\t'+s.draw() for s in db.get(self.shapes)])
>     return 'Page: %s\n%s\n' % (self.name,drawing)
>
> class Shape(db.Model):
>   color  = db.StringProperty(required=True,default='black')
>   @classmethod
>   def create(cls,onPage,**kwds):
>     s = cls(**kwds)
>     s.put()
>     onPage.shapes.append(s.key())  # maybe better to put this in a transaction
>     onPage.put()
>   def draw(self):
>     return ''
>
> class Create(webapp.RequestHandler):
>   def get(self):
>     page = Page(name='Number1')
>     page.put()
>     Line.create(onPage=page,endX=10,endY=5,color='red')
>     Line.create(onPage=page,startX=10,startY=5,endX=5,endY=-10,color='orange')
>     page = Page(name='Number2')
>     page.put()
>     Line.create(onPage=page,endX=1,endY=5)
>     Circle.create(onPage=page,startX=5,startY=0,radius=3,color='green')
>     self.redirect('/')
>
> ------------------------------------------------- code section 2 END
> --------------------------------------------------------------------------- 
> --------
--~--~---------~--~----~------------~-------~--~----~
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