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 google-appengine@googlegroups.com
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