1

I am trying to get all parent/children from a one to many relationship. Traditionally, I could do this with a join, but doing so in the datastore is escaping me.

I have found several partial examples to do this, but not one that is complete yet.

I have:

class Owner(db.Model):
  name = db.StringProperty()

class Pet(db.Model):
  petname = db.StringProperty()
  owner = db.ReferenceProperty(Owner, collection_name='pets')

#now I want to print all pets owned by scott
scott = Owner(name="scott")
scott.put()
Pet(owner=scott,petname="rufus").put()

pets = Pet.all().filter('owner =', "scott").fetch(100)
print Pet.all().filter('owner =', "scott").fetch(0)
stubble jumper
  • 275
  • 1
  • 4
  • 10

3 Answers3

4

Your query should work fine if you remove the quotes around "scott", I think.

You could also make all of Scott's Pet entities have his entity as their parent:

class Owner(db.Model):
    name = db.StringProperty()

class Pet(db.Model):
    petname = db.StringProperty()

scott = Owner(name="scott")
scott.put()

Pet(parent=scott, petname="rufus").put()
Pet(parent=scott, petname="fluffy").put()
Pet(parent=scott, petname="snoogums").put()

pets = Pet.all().ancestor(scott).fetch(100)
# Feed pets to your templating engine. So to speak.

By making scott the parent of the Pet entities, they are all added to the same entity group, and the ancestor query gives you a simple and stragihtforward way to get all of the Pet entities that are children of the given `Owner'. You should get much better performance with an ancestor query than a non-ancestor query.

This does impose the limitation that the Pet entities can only belong to one entity group, and if you wanted to have a Pet involved in multiple data relationships, you would have to choose another approach. If it is a one-to-one relationship, just storing a Reference to the other related entity.

To have a printable representation of your Pet entity, give it a __unicode__ method, something like this:

class Pet(db.Model):
    petname = db.StringProperty()

    def __unicode__(self):
        return "I am " + self.petname

__unicode__ should return a string with the information that you want to see printed by the print statement. As Nick wisely points out in comments, you should not use print in an AppEngine application. The SDK comes with Django templates and Jinja2. Use one of those or import one that you prefer.

Adam Crossland
  • 14,198
  • 3
  • 44
  • 54
  • I think that might be what I am looking for, but how do I print them out? If I just: print pets I get: [<__main__.Pet object at 0x10859df50>, <__main__.Pet object at 0x1085904d0>, <__main__.Pet object at 0x107bccb50>] – stubble jumper Apr 09 '12 at 16:05
  • Answered your question, @stubblejumper – Adam Crossland Apr 09 '12 at 16:13
  • Note that `__repr__` is intended to return a 'code' representation of an object; `__unicode__` is the method to use for a human-readable representation - but you should probably use a templating system and output just the bits you care about in the current situation. And you really, really, really shouldn't use 'print' in an App Engine app. – Nick Johnson Apr 10 '12 at 05:40
  • In fact, `print` in an App Engine app is an almost automatic downvote from me, only the rest of Adam's answer is excellent. :) – Nick Johnson Apr 10 '12 at 05:40
  • That's funny, Nick. I almost always remember to encourage people not to use print, but because he asked it as a comment rather than as part of the actual question, I sort blanked out on that. – Adam Crossland Apr 10 '12 at 16:51
0

Look at The GQL examples made by google.

Use the owner name as unique key giving 'scott' to key_name instead of 'name' when instanciating Owner.

scott = Owner(key_name="scott")

Create the pet with scott as parent

pet = Pet(key_name='rufus', parent=scott)

And query his pets with

SELECT * FROM Pets WHERE ANCESTOR IS KEY('Owner', 'scott')
KurzedMetal
  • 12,540
  • 6
  • 39
  • 65
0

You should filter by Key of Owner:

#not str "scott", use scott object.
pets = Pet.all().filter('owner =', scott).fetch(100)
najeira
  • 3,133
  • 2
  • 19
  • 21