Jason Rowe

Be curious! Choose your own adventure.

Blogging with Google App Engine

 

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:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *