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?