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

yojikのlog

yojikのブログです

Google App Engine を少しだけ触った

触ってみました。面白そうですねー。ホスティング機能だけではなく、付属のGoogle謹製のWeb Frameworkが何となくカワイイ感じです。
とりあえず、そこに絞ってメモしています。(ちなみに、このエントリはちょこちょこ修正しています)
このフレームワークを使う場合のステップは超簡単。

アプリケーション用ディレクトリを作ってマニフェスト(app.yaml)を書く

application: yojiksample
version: 1
runtime: python
api_version: 1

handlers:
- url: .*
  script: miniblog.py

自分のアプリとして登録したアプリーション名*1、そのアプリのバージョン、利用APIのバージョンを記述します。handlersにはURLに対して、どのスクリプトで対応するか書くようです。今回はminiblog.pyという名前にしました。

モデルを書く

先ほどのyamlで指定したスクリプト(miniblog.py)にモデル定義を記述します。ほぼ付属のサンプルGuestBookのパクリなので偉そうなことは言えませんが、、

class Entry(db.Model):
  title  = db.StringProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

これでOR*2マッピングまで完了。Entryのインスタンスをいきなり永続化すればよいだけです。

Viewを書く

viewの内容もminiblog.pyに書いていきます*3
Viewの定義はREST風味です。webapp.RequestHandlerクラスを継承して、get,post,head,options,put,deleteメソッドをオーバーライドすることにより、リソースを定義します。
以下は殆ど付属Guestbookのパクリです。

class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.out.write('<html><body>')
    entries = db.GqlQuery("SELECT * "
	                            " FROM Entry"
        	                    " ORDER BY date DESC LIMIT 10")  
    for e in entries:
      self.response.out.write('<div>')
      self.response.out.write('<b>%s</b>:' %     cgi.escape(e.title))
      self.response.out.write('<p>%s</p>:' % cgi.escape(e.content))
      self.response.out.write('</div>')
    self.response.out.write("""
          <form action="." method="post">
            <div><input type="text" name="title"></input></div>
            <div><textarea name="content" rows="3" cols="60"></textarea></div>
            <div><input type="submit" value="MiniBlog"></div>
          </form>
        </body>
      </html>""")

  def post(self):
    ent = Entry()
    ent.title = self.request.get('title')
    ent.content = self.request.get('content')
    ent.put()
    self.redirect('/')

getメソッドは原始的ですが、一応テンプレートエンジンもあるようです。
postメソッドをみると、Formからのリクエストはそれなりにself.requsetにマッピングされていることが分かります。そして、db.Modelをnewして、put()をメソッド呼ぶだけで永続化しています。
ちなみに、ここでは何のチェックもしてないのでデータを突っ込み間違えると悲惨なことになります。

マッピングを書く

スクリプト末尾に以下を追加します。

application = webapp.WSGIApplication([('/', MainPage)], debug=True)

こんな感じです。配列のところにURLとRequestHandlerの組を入れていく感じですね。
最後におまじない的なコードです。

def main():
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':

これで終了。

テスト起動

G.A.E.のディレクトリに移動して起動します。yojiksampleというのが今作った一式が入ってるアプリケーションディレクトリです。

python dev_appserver.py yojiksample

これで、アプリケーションがlocalhost:8080で起動します。ね、簡単でしょう。

ちなみにBigTableに永続化されたデータはどこに存在するのか気になります。Windowsの場合は以下のテンポラリファイルに格納されているようです。

Documents and Settings\(ユーザ名)\Local Settings\Temp\dev_appserver.datastore
Documents and Settings\(ユーザ名)\Local Settings\Temp\dev_appserver.datastore.history

アップロード

appcfg.pyでGoogleAppEngine本体にアプリケーションをアップロードしたり、一度上げたバージョンをロールバックさせたりできるようです。

python appcfg.py update (アプリケーションディレクトリ名)

この後、gmailアカウントのアドレスとパスワードを入力したらアップロードして完了です。簡単すぎる。

感想

ここでは触れませんでしたが、Google Accountsのユーザ認証を利用する機能も付いてるので、かなり使い勝手がありそうです。
少し癖がありそうなのは、BigTable用のスキーマ設計です。joinという概念が無かったり、カラムの中にリストを入れるListPropertyがあったり、かなり異質な感じです。この例では、BlogのEntryにぶら下げるコメント情報なんかはListPropertyで実現するんだろうなーと思いますが、、圧倒的にノウハウが足りてない。

それはともかく、この仕組みは素晴らしいですねー。すごく気楽にアプリを作って公開できるので、いわゆるSituatedSoftwareを作るときに役立つと思います。
例えば、ちょっとした宴会の予定あわせ用アプリとか(いい例が思いつかない)

*1:http://appengine.google.com/で登録したもの

*2:RDBじゃないですが

*3:とりあえず1ファイル主義でいきましょう