RequestHandler
GAE/Pythonで最初に戸惑うのはRequestHandlerだと思います。新規アプリケーション作成時に自動生成されるので必要に応じて書き換えることができれば問題ありません。
RequestHandlerとは
GAEにおいて xxx というIDでアプリケーションを公開すると http://xxx.appspot.com/ というURLが割り当てられます。ウェブアプリケーションには、トップページ、記事のリスト、記事の詳細など複数のページがありますが、それぞれのページにどういうURLを割り当てますか?こんな感じに割り当てる場合が多いと思います。RequestHandlerの役割はURLと処理を結びつけることです。
- トップページ
http://xxx.appspot.com/ - 記事一覧ページ
http://xxx.appspot.com/list - 個別記事ページ
http://xxx.appspot.com/detail/1
解説の流れ
以下の流れで解説します。
- Hello World!
アプリケーション作成時に、自動生成されるコードを解説 - 複数のRequestHandler
RequestHandlerを複数作成する例 - 正規表現を使ったリクエストハンドラ
RequestHandlerの条件に正規表現を使う例 - GET引数とPOST引数の処理
GETやPOSTで値を受け取る例
1. Hello World!
Google App Engine Launcherの、File > Create New Application… から新しいアプリケーションを作成すると、Hello world! と表示するRequestHandlerが生成されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/env python from google.appengine.ext import webapp from google.appengine.ext.webapp import util class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('Hello world!') def main(): application = webapp.WSGIApplication([('/', MainHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main() |
2-3行目
webappモジュールとutilモジュールをインポートしています。
5行目
webapp.RequestHandlerクラスを継承したMainHandlerクラスを定義しています。
6-7行目
getでアクセスした場合に、このメソッドが実行されます。self.response.out.write()の引数がWebブラウザに返されます。
10行目~11行目
重要な部分は、[(‘/’, MainHandler)]です。”/”へのアクセスをMainHandlerに渡すように設定しています。
13行目~14行目
このpyファイルが直接呼び出されたときにmain関数を実行します。書き換えることはないので、おまじないだと思って問題ありません。
2. 複数のRequestHandler
リクエストハンドラーを複数用いた例です。
- MainHandler
ルートディレクトリに対するリクエストを処理します。 - Page1Handler
/page1 に対するリクエストを処理します。 - Page2Hander
/page2 に対するリクエストを処理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/usr/bin/env python from google.appengine.ext import webapp from google.appengine.ext.webapp import util class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('MainPage <a href="/page1?phpMyAdmin=cfc2644bd9c947213a0141747c2608b0">Page1</a> <a href="/page1?phpMyAdmin=cfc2644bd9c947213a0141747c2608b0">Page2</a>') class Page1Handler(webapp.RequestHandler): def get(self): self.response.out.write('Page1 [ <a href="/?phpMyAdmin=cfc2644bd9c947213a0141747c2608b0">Back to MainPage</a> ]') class Page2Handler(webapp.RequestHandler): def get(self): self.response.out.write('Page2 [ <a href="/?phpMyAdmin=cfc2644bd9c947213a0141747c2608b0">Back to MainPage</a> ]') def main(): application = webapp.WSGIApplication( [('/', MainHandler),('/page1', Page1Handler),('/page1', Page2Handler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main() |
3. 正規表現を使ったリクエストハンドラ
上記の2つのソースコードでは、URLは固定(定数)になっていましたが、記事番号などの変数を含めたい場合もあります。そういう場合は、リクエストハンドラーのURLに正規表現を使います。
- 11行目
‘/(.*)’を満たすURLにアクセスした場合にMainHandlerに処理を任せます。/の後ろに0文字以上の文字が続くという条件になっています。 例) /, /123, /hoge, /bakabakabaka - 6行目
getの引数が2つになりました。2番目の引数に、’/(.*)’の括弧の中の値が渡されます。 - 12行目
渡された引数をそのまま表示しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env python from google.appengine.ext import webapp from google.appengine.ext.webapp import util class MainHandler(webapp.RequestHandler): def get(self, value): self.response.out.write("value = %s" % value) def main(): application = webapp.WSGIApplication( [('/(.*)', MainHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main() |
実行例
この方法で変数を渡すと、静的ページのように見えるので、SEOに良いはずです。(とはいえ、最近の検索エンジンは賢いので、わざわざ静的ページに見えるようにしなくても大丈夫かもしれません。)
4. GET引数とPOST引数の処理
GETとPOSTでの値の受け取り例を紹介します。
- 7行目
GETでvalueに渡された値を取り出す。GETで渡された変数も、POSTで渡された変数も同じ関数で取り出せます。 - 8行目
GETで渡された変数を画面に表示。 - 9行目~13行目
入力フォームを表示します。MethodはPOSTで、送信先は”/”を指定しています。 - 14行目~16行目
POSTを受け付けた場合はpostメソッドが呼び出されます。POSTで渡された値もGETで渡された値と同じ方法で取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/env python from google.appengine.ext import webapp from google.appengine.ext.webapp import util class MainHandler(webapp.RequestHandler): def get(self): value = self.request.get('value') self.response.out.write(value) self.response.out.write(""" <form method="post" action="/"><input type="hidden" name="phpMyAdmin" value="cfc2644bd9c947213a0141747c2608b0" /> <input type="text" name="postvalue"/> <input type="submit" value="submit"/> </form>""") def post(self): postvalue = self.request.get('postvalue') self.response.out.write(postvalue) def main(): application = webapp.WSGIApplication( [('/', MainHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main() |
実行例
/?value=python にアクセスすると、GETでvalueに文字列”python”が渡され、ブラウザにpythonと表示される。
テキストフィールドに文字を入力して、ボタンをクリックすると・・・
まとめ
以上の内容を理解すれば、データを保存しないタイプのWebサイトを構築できるようになります。データの保存はDataStoreを使って行うのが一般的。