Why GQL Query does not match?
-
21-08-2019 - |
Question
What I want to do is build some mini cms which hold pages with a uri.
The last route in my urls.py points to a function in my views.py, which checks in the datastore if there's a page available with the same uri of the current request, and if so show the page.
I have a model:
class Page(db.Model):
title = db.StringProperty(required=True)
uri = db.TextProperty(required=True)
created = db.DateTimeProperty(auto_now_add=True)
modified = db.DateTimeProperty(auto_now=True)
content = db.TextProperty()
In my view:
def show(request):
page = db.GqlQuery('SELECT * FROM Page WHERE uri=:uri', uri=request.path).get()
if page is None:
return http.HttpResponseNotFound()
else:
return respond(request, 'pages_show', {'content': request.path})
And I've added an entity with '/work' as uri to the datastore.
Even when request.path is exactly '/work', the query does not return a match.
Thanks for any advice you can give me!
And yes, i'm a python noob, App Engine is perfect to finally learn the language.
Solution
I've found the solution!
The problem lies in the model.
App engines datastore does not index a TextProperty. Using that type was wrong from the beginning, so i changed it to StringProperty, which does get indexed, and thus which datastore allows us to use in a WHERE clause.
Example of working model:
class Page(db.Model):
title = db.StringProperty(required=True)
// string property now
uri = db.StringProperty(required=True)
created = db.DateTimeProperty(auto_now_add=True)
modified = db.DateTimeProperty(auto_now=True)
content = db.TextProperty()
OTHER TIPS
If you use named keyword arguments ("uri=:uri"), you have to explicitly bind your parameters to the named keyword. Instead of:
# incorrect named parameter
GqlQuery('SELECT * FROM Page WHERE uri=:uri', request.path).get()
you want
# correct named parameter
GqlQuery('SELECT * FROM Page WHERE uri=:uri', uri=request.path).get()
or you could just use a positional parameter:
# correct positional parameter
GqlQuery('SELECT * FROM Page WHERE uri=:1', request.path).get()