views:

707

answers:

2

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.

+2  A: 

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()
Clint
Yes, i provided a wrong example. Even with using the named parameter or the positional parameter, i still get the same result. Corrected the sample now, thanks!
Sander Versluys
A: 

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()
Sander Versluys
You don't actually need the uri property at all. If you create Page entities with their key_name equal to the URI, you can look it up with Page.get_by_key_name(uri), and you get uniqueness for free!
Nick Johnson
Ah great idea Arachnid. I want to +1 for your tip :-) Thanks!
Sander Versluys