Need Help with Datastore Query

151 views
Skip to first unread message

Ms. Jen

unread,
Dec 28, 2009, 1:33:03 AM12/28/09
to Google App Engine
Hello All(),

I have been struggling with attempting to run a datastore query and
keep getting the same error even though I have read through all the
docs on Queries and Keys, watching several of the Google I/O videos,
as well as looking at a number other apps' source code to see how they
are done.

The error I get is:

Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/
GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/
google/appengine/ext/webapp/__init__.py", line 507, in __call__
handler.get(*groups)
File "/Users/msjen/Dev/alex/alexsbarbooking/editband.py", line 41,
in get
self._displayEditBandPage()
File "/Users/msjen/Dev/alex/alexsbarbooking/editband.py", line 32,
in _displayEditBandPage
raise ValueError, 'Band with ID %d does not exist.' % id
ValueError: Band with ID 2 does not exist.

My code is:
id = int(self.request.get('id'))
band_id = Band.get(db.Key.from_path('Band', id))
if band_id:
band_query = Band.gql("WHERE ID = ", id)
band = band_query.fetch(1)
self.response.out.write('Band query successful. %s : %d' %
band.band_name, id)
if not band_edit:
raise ValueError, 'Band query with ID %d did not get the info
from the datastore.' % id
if not band_id:
raise ValueError, 'Band with ID %d does not exist.' % id

I have imported the db.model of band:
from band import Band

The other error I get if I use other code samples is that the global
variable of 'band' is not recognized, even though I have imported the
model.

the URL path that I am requesting the id from is: http://localhost:8080/editband/?id=2
And I am able to run a self.write.reponse to write out the requested
id from the path.

The problem seems to lie in passing the requested path id into the
query where I want to filter it by the requested id.

Please, please, tell me that another set of eyes can spot what I am
doing wrong here....

Thanks in advance,
Jen

N. Rosencrantz

unread,
Dec 28, 2009, 2:37:53 AM12/28/09
to Google App Engine
Official advice seems be Meta in this case
class BandForm(djangoforms.ModelForm):
    class Meta:
        model = Band
wheres a very good gae editor in least codebase is available
http://code.google.com/appengine/articles/djangoforms.html

Ms. Jen

unread,
Dec 28, 2009, 2:10:33 PM12/28/09
to Google App Engine

I tried the Meta and DjangoForms and it still did not work.


On another attempt, I tried this with the Meta & djangoforms:

id = int(self.request.get('id'))

band_id = Band.getBandByID(id)
query = Band.gql("WHERE ID = :1",
'band_id')
band_edit = query.get()
self.response.out.write(template.render('editband.html',
{'band_edit':
band_edit }))

which will render the page but not the form between the

{% for band in band_band %} {% endfor %}

in the template and it is not displaying the Band.db entity
properties.

If I add :
for band in band_edit:
self.response.out.write(template.render('editband.html',
{'band_edit':
band_edit }))

I then get the error:
TypeError: 'NoneType' object is not iterable

Which leads me to think that the id as band_id is not being passed to
the query.

Anyone?


Niklas Rosencrantz

unread,
Dec 29, 2009, 7:38:03 AM12/29/09
to google-a...@googlegroups.com
expensive instruction to redo or question is
int(self.request.get('id')) so avoid casting for 1
2009/12/28 Ms. Jen <black...@gmail.com>:
> --
>
> 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-a...@googlegroups.com.
> To unsubscribe from this group, send email to google-appengi...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en.
>
>
>

Ms. Jen

unread,
Dec 29, 2009, 2:51:39 PM12/29/09
to Google App Engine
Avoid casting for what? The number 1 or for an id?

Are you saying that one should not be attempting to request a
datastore ID from a URL? From a search of this and other groups, over
a year ago there was a bug in getting by the ID, but it is not a bug
anymore.

If I take out the in(self.request.get('id')), then I get an error that
says:
BadValueError: Unsupported type for property : <type
'builtin_function_or_method'>

Do you have another way that you prefer to pass an identifier in the
URL path that then the identifier may be passed to the next datastore
search? If so, please send link.

Robert Kluin

unread,
Dec 29, 2009, 3:43:58 PM12/29/09
to google-a...@googlegroups.com
Hi Jen, have you considered using a key "name" instead of an id? Then
instead of needing to use an "int," your "id" can be a string?

Robert

Wesley Chun (Google)

unread,
Dec 29, 2009, 4:02:48 PM12/29/09
to Google App Engine
howdy jen... great to see you on App Engine!

as far as your problem goes, have you checked to see just what *are*
the IDs of the objects you've stored? you seem to be trying to select
them, but perhaps their values are not what you're expecting (hence
the query failures).

i would just like to see a query that pulls up your data entities then
displays their IDs if 'id' is a property of your object. if you're
just creating and storing them with put, you're taking the default ID
that App Engine assigns, so in these cases, you need to fetch an
entity's key in order to get to its ID... something like this:

bands = Band.gql('')
for band in bands:
self.response.out.write('<br>%s: %s<p>\n' % (band.key().id_or_name
(), band.band))

let us know what you get!

cheers,
-wesley
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Core Python Programming", Prentice Hall, (c)2007,2001
"Python Fundamentals", Prentice Hall, (c)2009
http://corepython.com

wesley.j.chun :: wesc...@google.com
developer relations :: google app engine

Stephen

unread,
Dec 29, 2009, 4:22:01 PM12/29/09
to Google App Engine

On Dec 28, 6:33 am, "Ms. Jen" <blackpho...@gmail.com> wrote:
>

> I have been struggling with attempting to run a datastore query and
> keep getting the same error even though I have read through all the
> docs on Queries and Keys, watching several of the Google I/O videos,
> as well as looking at a number other apps' source code to see how they
> are done.


This bit doesn't make sense:

>     id = int(self.request.get('id'))
>     band_id = Band.get(db.Key.from_path('Band', id))


Band.get(key) returns a model, not an 'id'. But there is an easier
way:

a_band_instance = Band.get_by_id(id)

Given the above, this next section doesn't make sense because you
already have a band object:

>     if band_id:
>       band_query = Band.gql("WHERE ID = ", id)
>       band = band_query.fetch(1)


Unless you specifically created an 'ID' attribute in your Band model,
you are probably mistaking it for the built-in '__key__' attribute,
which is what get() and get_by_id() use in the first example.

if not band_instance:
# The 'id' you are passing in is wrong.
# Where did you get it from?


You could log in to the admin interface and use the data browser to
double-check what Band models you have saved.

G

unread,
Dec 29, 2009, 5:24:00 PM12/29/09
to Google App Engine
A previous version of the AppEngine docs claimed that key_name values
couldn't be numbers (or start with numbers). Perhaps that is related
to the year old bug you describe?

The current AppEngine docs have been revised (only the double
underscore case remains), and a quick test confirms that 'numeric'
key_name are allowed (as long as they are expressed as strings).

o = Model.get_by_id( 42 )
o = Model.get_by_key_name( '56' )

The source of the value doesn't matter (URL, whatever). The type does
matter.

o = Model.get_by_id( int( v ) )
o = Model.get_by_key_name( str( v ) )

Deciding which to use, from a mixed source (ids and key_names), can
still be tricky. :)

--
G

Niklas Rosencrantz

unread,
Dec 29, 2009, 6:29:00 PM12/29/09
to google-a...@googlegroups.com
2009/12/29 G <cultu...@gmail.com>:
regex webapp.WSGIApplication('/([0-9]*)',AnyById), def get(self, id),
key = str(db.Key.from_path('Any', int(id)))
any = db.get(db.Key(key))
Like thing By Id, Nameconventional somewhat related to "good name"
which could mean anything preferably ISO standard that lags newest
stuff we can use numbers to free space comparing AbyB and B2A. I now
use first convention like ThingById getting regexed id avoiding
casting stating Id2Thing compared to ThingById from montao.googlecode

Ms. Jen

unread,
Dec 30, 2009, 12:49:48 AM12/30/09
to Google App Engine
Hi Wesley!

I have been putting about GAE for a year now, but only in the last few
months have hit a wall trying to combine what I know Python can do vs.
what the docs say GAE can do.

One of the first things I did was to make sure that the first two
lines of code were actually able to get and call the ID in question.
I had a test logging line that was able to get the accurate ID #.

So the real issue I am having is will GAE allow me to pass a dynamic
variable into the datastore? Most all of the examples in the docs are
literal strings, thus I was not sure if I should be encasing the
variable in quotes or not.

Ms. Jen

unread,
Dec 30, 2009, 12:54:56 AM12/30/09
to Google App Engine
Thanks all for your replies and input.

I was avoiding using the entity Key, as it is such a mix of
alphanumeric and the entity ID is a straight iterative integer, which
makes for a cleaner URL.

I will try the above in the morning and report back how it goes.

Ms. Jen

unread,
Jan 3, 2010, 8:19:43 PM1/3/10
to Google App Engine
Thanks everyone for your replies! Happy New Year.

Hi Wesley - You rock, your solution worked. Now I want to know why
it worked. ;o)

Here is the code that is rendering my edit band page per your
suggestion:

def get(self):
band_edit = Band.gql('')
for band in band_edit:
template_values = {
'band_edit': band_edit,
}
path = os.path.join(os.path.dirname(__file__), 'editband.html')
self.response.out.write(template.render(path, template_values))

How does the second line of Band.gql('') know to pull the band.key.id
from the URL and then use it to only grab the Band entity with the ID
of 2?
Or is it because I have my application = webapp.WSGIApplication mapped
to ('/editband/?$', EditBand) in my main.py? Does python then look
for whatever is the ?$ and then uses that to run the Band.gql('')?

Inquiring minds wish to understand the zen of abstract Python.

Thanks!

Ms. Jen

unread,
Jan 3, 2010, 8:30:10 PM1/3/10
to Google App Engine
Oh, never mind on my last message dated Jan 3 at 5:19pm. On my
localhost, the query only ran for the only entity I had, but when I
deployed it, I got 6 bands and not just the band by the id I wanted.

Back to drawing/hacking board.

Ms. Jen

unread,
Jan 4, 2010, 1:00:50 AM1/4/10
to Google App Engine
Ok, the results of an evening spent reading docs, searching for
answers, and otherwise beating my head against the GAE wall, is the
following:

If I pass the band name (band.band_name) on the URL, I am able to
search for it in the datastore with:

band_edit = Band.gql("WHERE band_name = 'id'")

And the page is rendered with just the band in question and not a
whole list of them. Well, that was easy. So, why don't I use it?
Because people can have several bands of the same name or misspell the
name or the like, and a unique ID as the entity ID would be much more
useful and accurate over time.

But if I try with the ID or Key, I have no luck. If I pass the ID as
band_id and then put it to the database as another string or integer
entity named band_id, and then try and search the datastore as above:

band_edit = Band.gql("WHERE band_id = 'id'")

I have no luck. None. (Yes, None with a big N). Either I get a
blank page or I am told that it can't iterate Band or there is an
integer or string error.

According to: http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Queries_on_Keys
there are limited queries on Keys and IDs allowed.

I know that folks can do it, as I have seen GAE python based apps that
call individual entities by a URL id. Yes, the docs say you can, but
with no concrete examples. Is there a cookbook recipe for how to get
by ID or Key?

Wesley Chun (Google)

unread,
Jan 5, 2010, 10:20:12 PM1/5/10
to Google App Engine
hi jen,

apologies that i didn't explain Band.gql('') when i made my earlier
post.
that's pretty much of a "SELECT *" as you found out.

now, i'm not sure how you're storing your objects, but perhaps the IDs
are not the same as what you're expecting (i.e., 1, 2, etc.). would it
be
possible for you to post your model (or at least part of it) so we can
see
what you have?

can you also provide the code you're using to put your objects into
the
datastore with?

the reason why i'm asking is because a default "ID" that App Engine
assigns is always going to be unique and auto-incrementing. you have
the option of giving a key_name instead of taking the default, so if
you
don't specifically specify the IDs, then they're auto-generated for
you.

finally, if you wish for me to take a look at your application, please
provide your application ID (usually APP_ID.appspot.com) or whatever
you put after "application: " in your app.yaml file.

thanks!
-- wesley


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Core Python Programming", Prentice Hall, (c)2007,2001
"Python Fundamentals", Prentice Hall, (c)2009
http://corepython.com

wesley.j.chun :: wesc...@google.com
developer relations :: google app engine

On Jan 3, 10:00 pm, "Ms. Jen" <blackpho...@gmail.com> wrote:
> Ok, the results of an evening spent reading docs, searching for
> answers, and otherwise beating my head against the GAE wall, is the
> following:
>
> If I pass the band name (band.band_name) on the URL, I am able to
> search for it in the datastore with:
>
> band_edit = Band.gql("WHERE band_name = 'id'")
>
> And the page is rendered with just the band in question and not a
> whole list of them.  Well, that was easy. So, why don't I use it?
> Because people can have several bands of the same name or misspell the
> name or the like, and a unique ID as the entity ID would be much more
> useful and accurate over time.
>
> But if I try with the ID or Key, I have no luck.  If I pass the ID as
> band_id and then put it to the database as another string or integer
> entity named band_id, and then try and search the datastore as above:
>
> band_edit = Band.gql("WHERE band_id = 'id'")
>
> I have no luck.  None.  (Yes, None with a big N).     Either I get a
> blank page or I am told that it can't iterate Band or there is an
> integer or string error.
>

> According to:http://code.google.com/appengine/docs/python/datastore/queriesandinde...

Ms. Jen

unread,
Jan 6, 2010, 1:20:48 AM1/6/10
to Google App Engine
Hi Wesley!

Bizarrely, or not so much, many solutions to ongoing/hard problems
come to me at night, so during a bout of insomnia the night before
last, my brain said, "Research how to get by Key, then unit test for
ID in the SDK console." And so, I did today and it now is working!
Yay.

Here is the solution I found, since I did want to use the unique ID
but didn't quite know how to get there as I kept getting different
errors.

Code that is now working happily:
k = self.request.get('id')
q = int(k)
band = Band.get_by_id(q)
template_values = {
'band': band,


}
path = os.path.join(os.path.dirname(__file__), 'editband.html')
self.response.out.write(template.render(path, template_values))

In explanation, I had to separate out the requesting of the id in the
string of the URL from making the id an integer before getting from
the datastore, as every time I tried to combine the first two lines
into
k= int(self.request.get('id'))
I got an error about integers as noted in one of my many emails above.

Now it is working, I have a clean URL, as I did not want to use the
Key, and I don't have to worry about using the band name in the URL.
I have two more things to fix in the post part of edit band, and then
I can share the url on appspot with you all.

Once again, thanks for all the input.

Reply all
Reply to author
Forward
0 new messages