ログインが必要なメソッドを実装するための Google App Engine アプリ用デコレータ

Google App Engine アプリを作っていると、「ログインしていないときはログインページにリダイレクトする」コードをよく書きます。

class MainHandler(webapp.RequestHandler):
    def get(self):
        # ログインしていないときは、ログインページにリダイレクト
        if not users.get_current_user():
            self.redirect(users.create_login_url(self.request.uri))
            return
        self.response.out.write('Hello world!')

ログインが必要なメソッドの先頭で、このコードを毎回記述するのは面倒です。かといって、共通化しようにも、ベースクラスを用意してヘルパーメソッドを定義するのはイマイチ。

そこで思いついたのが、Python のデコレータを使う方法。

# ログインしているか先にチェックするデコレータ
def login_required(original_func):
    def decorated_func(arg, *args, **keywords):
        if not users.get_current_user():
            arg.redirect(users.create_login_url(arg.request.uri))
            return
        original_func(arg, *args, **keywords)
    return decorated_func

class MainHandler(webapp.RequestHandler):
    # ログインしてないと get メソッドは実行できない
    @login_required
    def get(self):
        self.response.out.write('Hello world!')

ログインが必要なメソッドに @login_required を付けるだけ。ベースクラスを作ってヘルパーメソッドを定義する方法より、はるかにスマート。

もう、Python のデコレータに心酔です。

追記

google.appengine.ext.webapp.util に login_required っていう同名のデコレーターが用意されていました。でもこれ、get メソッドにしか使えない。「GET だけで十分」という人は、そちらを使うほうがいいです。