mFontoura
mFontoura

Reputation: 257

How do I use a reference key on a query?

I have this two models: Tutorial and Chapter. Chapters have a key reference to the tutorial they belong. Now I'm trying to list all the chapter that belong to a specific Tutorial but I can't get the query to work:

class TutView(FuHandler):
    def get(self):
        tutKey = self.request.get('tut_key')
        tut = db.Key.from_path('Tutorial', tutKey)
        chaps = db.GqlQuery("SELECT * FROM Chapter " +
                            "WHERE __key__ = KEY('Tutorial', :1)", tut)
        self.render('tutView.html', chaps=chaps)

When running I get this error:

BadArgumentError: Expected an integer id or string name as argument 2; 
received datastore_types.Key.from_path(u'Tutorial', u'<bound method 
Tutorial.key of <main.Tutorial object at 0x00.............

Chapter model:

class Chapter(db.Model):
    tutorial = db.ReferenceProperty(Tutorial, collection_name='chapters')
    title = db.StringProperty(required=True)
    content = db.TextProperty(required=True)

Tutorial model:

class Tutorial(db.Model):
    title = db.StringProperty(required=True)
    presentation = db.TextProperty(required=True)

update: i managed to get no errors but i get no results (so, probably it's wrong):

chaps = db.GqlQuery("SELECT * FROM Chapter " + 
                    "WHERE __key__ = KEY('tutorial', :1)", str(tutKey))

update2: The problem might be on the way i store or retrieve the tutKey. I'm getting the key with the URL... and and that's probably not working... but i don't know other way

Upvotes: 0

Views: 304

Answers (3)

The KEY() GQL function is used to create Keys based on two parameters: The Entity, and the name/id. If you look at your code, you will see that you are passing it a db.Key object as a parameter. Hence, the error message:

Expected an integer id or string name as argument 2; 
received datastore_types.Key.from_path(u'Tutorial', ...)

Also, you need to test against the tutorial property of the Chapter entity, and not against its own __key__.

I do not work with GQL, I use the Query objects instead. You provide them with the db.Key object directly, so I assume this should work:

chaps = db.GqlQuery("SELECT * FROM Chapter " +
                        "WHERE tutorial = :1", tut)

If it doesn't, you can always try:

chaps = db.GqlQuery("SELECT * FROM Chapter " +
                        "WHERE tutorial = KEY('Tutorial', :1)", tut.id() or tut.name())

Upvotes: 1

user784435
user784435

Reputation:

start an app locally and run the interactive console:

http://127.0.0.1:8080/_ah/admin/interactive

copy and paste the code bellow into the console You can easily try different things and print out the results

from google.appengine.ext import db


class Tutorial(db.Model):
    title = db.StringProperty(required=True)
    presentation = db.TextProperty(required=True)

class Chapter(db.Model):
    tutorial = db.ReferenceProperty(Tutorial)
    title = db.StringProperty(required=True)
    content = db.TextProperty(required=True)

a = Tutorial(title="First tut", presentation="first")
a.put()

print a
print a.key().id()

b = Chapter(tutorial=a, title="tut2", content="lots of words")
b.put()

print b
print b.key().id()

chap = Chapter.all().filter("tutorial =", a).fetch(1000)

for i in chap:
  print i.tutorial.title

Upvotes: 0

Shay Erlichmen
Shay Erlichmen

Reputation: 31928

You don't need a query to return an entity from key just use:

chaps = Tutorial.get(tut).chapters 

Upvotes: 2

Related Questions