A recent post and talk on twitter about host providers got me interested in building a blog using Google App Engine (GAE). It’s free to use and would eliminate having to pay for a hosting provider for a small site. My blog turned out like this jsoncharts. I’m pretty happy with it so far.
I got started with Python and GAE by reading the documentation and using the examples on the Google App Engine site. Then I used this article and framework for the base of my blog. The major changes I made were adding commenting and friendly URL’s. I can have URL’s like this (http://jsoncharts.appspot.com/blog/force-directed-graph-with-raphael) and comments on the articles (http://jsoncharts.appspot.com/blog/force-directed-graph-with-raphael#respond).
Adding friendly URL’s was easy enough. Following Bret Taylor’s example here is what my WSGIApplication instance looks like.
application = webapp.WSGIApplication( [('/', FrontPageHandler), ('/tag/([^/]+)/*$', ArticlesByTagHandler), ('/date/(\d\d\d\d)-(\d\d)/?$', ArticlesForMonthHandler), ('/'+ defs.ARTICLE_URL_PATH +'/(\d+)/?$', SingleArticleHandler), ('/'+ defs.ARTICLE_URL_PATH +'/([^/]+)', SingleArticleHandlerBySlug), ('/archive/?$', ArchivePageHandler), ('/rss2/?$', RSSFeedHandler), ('/.*$', NotFoundPageHandler), ],
The following line routes incoming request to a class handler named “SingleArticleHandlerBySlug”.
('/'+ defs.ARTICLE_URL_PATH +'/([^/]+)', SingleArticleHandlerBySlug),
The handler looks like this:
class SingleArticleHandlerBySlug(AbstractPageHandler): """ Handles requests to display a single article, given its unique ID. Handles nonexistent IDs. """ def get(self, slug): article = Article.get_for_slug(slug) comments = None if article: comments = Comment.get_all_by_articleId(article.id) template = 'show-single-article.html' articles = [article] more = None else: template = 'not-found.html' articles = [] self.response.out.write(self.render_articles(articles=articles, request=self.request, recent=self.get_recent(), template_name=template, comments=comments))
To add the commenting I had to create a new model class for storage. This was very simple.
class Comment(db.Model): name = db.TextProperty() email = db.TextProperty() website = db.TextProperty() body = db.TextProperty() commented_when = db.DateTimeProperty(auto_now_add=True) id = db.IntegerProperty() articleId = db.IntegerProperty() gravatar_url = db.TextProperty()
Then I added a few functions for finding and deleting and then added them in. I can’t remember ever doing something with storage this fast. I don’t miss SQL at all. GAE really hides all the storage implementation details for you. Here is an example of the functions used to access the data store.
@classmethod def get_all(cls): q = db.Query(Comment) q.order('-commented_when') return q.fetch(FETCH_THEM_ALL) @classmethod def get_all_by_articleId(cls, articleId): q = db.Query(Comment) q.filter('articleId = ', articleId) q.order('-commented_when') return q.fetch(FETCH_THEM_ALL)
That’s all it takes and you are ready to go.
Overall I was very impressed with the experience. In the future I’ll probably look into using Django’s form validation framework for comments and figure out how backups would work.
Post Related Links:
Leave a Reply