fredrik
fredrik

Reputation: 17617

Friendly URLs in Google App Engine

I'm trying to build a Friendly URL lookup method in GAE and Python. Have anyone done this?

I've got it working but it feels VERY shaky. How it works is that it takes the path (let's say /foo/bar/) and splits it to a list. Takes the last element in the list and query the database for a match. Now comes some headaches.

If there is more that one 'bar' since there could be another 'bar' but under a different page, how to tell them apart? As of now, my solution is to iterate over the result of 'bar' and look at a reference property to it's parent page. The parent 'foo' could also occur more then once so now we have to iterate over that to. It isn't hard to see that this cloud easily add up to a large number of for loops.

Just to make it a bit worse one page could be able in more then one language and the url need to match the give language.

My current datastore setup is this:

## Class to store pages.
class Pages(db.Model):
    name = db.StringProperty()
    ## Some more properties for storing content
    parentKey = db.SelfReferenceProperty()

## Class to store friendly url path segments
class UrlProvider(db.Model):
    name = db.StringProperty()
    path = db.StringProperty()
    langCode = db.StringProperty()
    page = db.ReferenceProperty(Pages)

And to fetch a page using firendly url:

pageFromUrl = UrlProvider.gql('WHERE path = :path AND langCode = :lang', path = path, lang = templateObject.lang).fetch(100)

for pageUrl in pageFromUrl:
    parentFromUrl = UrlProvider.gql('WHERE page = :page AND langCode = :lang', page = pageUrl.page.parentKey, lang = templateObject.lang).fetch(100)
    for parentUrl in parentFromUrl:
        if parentUrl.path == templateObject.path[-2]:
            templateObject.url = parentUrl.path + '/' + path
            page = pageUrl.page

What it does is, it fetches from UrlProvider everything that matches the last item in the templateObject.path list. Iterates over it and fetches all parents and trying to match it.

As of now it only works for one root page and one subpage. I don't know how to make it more dynamic and support multiple levels.

Have anyone written their own or have any good suggestions?

Upvotes: 3

Views: 1334

Answers (2)

Parker
Parker

Reputation: 8851

Is this what you're looking for? http://code.google.com/appengine/docs/python/tools/webapp/running.html#URL_Mappings

Instead of http://test.com/browse?category=book&productid=A209 you can have http://test.com/browse/book/A209

class BrowseHandler(webapp.RequestHandler):

def get(self, category, product_id):
    # Display product with given ID in the given category.


# Map URLs like /browse/(category)/(product_id) to BrowseHandler.
application = webapp.WSGIApplication([(r'/browse/(.*)/(.*)', BrowseHandler)
                                 ],
                                 debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()

Upvotes: 1

a.m.
a.m.

Reputation: 2208

http://code.google.com/appengine/docs/python/tools/webapp/running.html#URL_Mappings

Check out the section that says url mappings

this is complete code but I hope you get the idea

this is my request handler parama = my first param, paramb = my second param

class testPath(webapp.RequestHandler): def get(self,parama,paramb): # notice the 2 extra params, not just self self.response.out.write(parama) self.response.out.write(paramb)

.... # below you see i mapped anything that request "/test// notice the "r" before the 'urlmapping'

application = webapp.WSGIApplication([ (r'/test/(.)/(.)', testPath), ('/logout', LogoutHandler) ], debug=True)

so when i go to 'myapp.com/test/fruits/green

parama = fruit paramb = green

:D

Upvotes: 1

Related Questions