読者です 読者をやめる 読者になる 読者になる

全てのHTMLリクエストをPythonで処理してから出力する

【宣伝】下記のページでも利用している技術です。
共円(http://my-android-server.appspot.com/)


twitter連携などを行うと、ログイン状態や情報の取得など、全てのページで必要な処理が出てきました。
そのため、全てのHTMLリクエストをpythonのモジュールを通して処理するようにしてみました。


html.py

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import os
import logging
import math
import Cookie
import tweepy
import uuid
from google.appengine.ext import webapp, db
from google.appengine.api import memcache
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

def render_page(handler, page, values=None):
    template_values = values or {}
    # ここに常に行う処理を記述する(ログイン情報を'template_values'に詰めるとか)

    path = os.path.join(os.path.dirname(__file__), 'template', page)
    html = template.render(path, template_values)
    handler.response.out.write(html)

class StaticPage(webapp.RequestHandler):
    def get(self, value=None):
        if not value:
            value = 'index.html'

        render_page(self, value)

    def post(self):
        self.get(self)

application = webapp.WSGIApplication([('/', StaticPage),
                                      ('/page/(.*)', StaticPage),
                                      ], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

(import周りは精査するのがめんどくさくて、そのままですが・・・)

それ以外の部分は以前の記事とほぼ同じです。
GAE/Pythonで、テンプレートを利用したHTMLの表示 - 混沌とした備忘録


これにより、welcome pageとして、'template/index.html'が表示され、
それ以外の'/page/hogehoge.html'へのリクエストは、共通処理を行ったあとに、
'template/hogehoge.html'の内容が表示されます。


webapp.WSGIApplicationの引数に、'(.*)'のように記述すると、
get関数の、selfの次の引数(第一引数と言うの?)として渡されるようです。
その変数を'render_page'という自作の関数に渡し、その中で共通処理を実行します。
結果を'template_values'に入れたりして、引数で指定されたページをrenderに渡しています。


特別な処理が必要なページに対しては、

class HogePage(webapp.RequestHandler):
    def get(self):
        # 特別な処理
        render_page(self, 'hoge.html', template_values)

    def post(self):
        self.get(self)

application = webapp.WSGIApplication([('/', StaticPage),
                                      ('/page/hoge.html', HogePage),
                                      ('/page/(.*)', StaticPage),
                                      ], debug=True)

のように、'/page/(.*)'より前に記述したら、そちらが優先されます。


ログイン処理などの非機能要件(?)は、本来はロジックと分離すべきかとは思います。
ただ、Javaで言う、「javax.servlet.Filter継承のクラスをweb.xmlに登録」みたいな機能がGAE+Pythonで見つかりませんでした。
知ってる人がいたら、教えてください。


書いてる途中で気がつきましたが、継承とか使えば、もうちょっと綺麗に書けるかも・・・