webapp2公式ドキュメントを読み解く会(5回目)
2013年06月23日
今回も、横浜のコワーキングスペース「タネマキ」で、GAE/Pの勉強会を行いました。
その勉強会の中で、webapp2の公式ドキュメントを読み解く会を継続して行なっています。
今回は、URL routingの以下の項目からスタートです。
これを使うと、リクエストURLのパターンマッチングが出来るようになります。
| Format | Example |
|---|---|
| <name> | '/blog/<year>/<month>' |
| <:regex> | '/blog/<:\d{4}>/<:\d{2}>' |
| <name:regex> | '/blog/<year:\d{4}>/<month:\d{2}>' |
handler側でのパラメータの受け取り。
handler側では、パラメータとして以下のように受け取ることが出来ます。
nameありの場合は、**kwargsで受け取る
nameなしの場合は、*argsで受け取る
※nameありとnameなしの混在について
name ありとnameなしの混在とした場合は、
nameを付けた項目のみ、**kwargs で受け取ることが可能。
nameを付けていない項目は、パターンマッチングには利用できるが、handlerでは受け取ることはできない。
以下は、公式サイトのサンプルソース
Route('/<user_id>/settings', handler=SettingsHandler, name='user-settings')
Route('/<user_id:[^/]+>/settings', handler=SettingsHandler, name='user-settings')
handlerの設定を文字列で指定することが可能です。
handlerをフルパスで指定する必要があります。
application startup時に不要なhandlerをimportしなくなるため、起動が早くなるようです。
GAEでは、spin upのスピードは重要なので、なるべくこちらを使ったほうが良さそうですね。
以下公式サイトのサンプルソースです。
app = webapp2.WSGIApplication([ (r'/', 'handlers.HomeHandler'), (r'/products', 'products.ProductListHandler'), (r'/products/(\d+)', 'products.ProductHandler'), ])
ルート直下にある、handlers.py と products.pyにそれぞれhandlerを書いている想定になっています。
webapp2では、handler側での実装を、httpのメソッド(get、post、headなど)に併せて、def get や def postやdef headを実装することで、処理を行います。
この項目では、独自に作成したメソッドを呼び出すことが出来るようになります。
どんな時に使えるか?
あまり、使いドコロは思いつかない状況ではありますが、get postで同じメソッドを呼びたい場合などに、handlerに独自のメソッドを作成することが可能となります。
ただし、haedのリクエストの挙動も一緒になってしまうので、そのまま使うのは難しいかもしれません。
表記は2通りあります。
handler_methodで指定する方法。
webapp2.Route(r'/products', handler='handlers.ProductsHandler', name='products-list', handler_method='list_products')
handlerに:を使って指定する方法。
webapp2.Route(r'/products', handler='handlers.ProductsHandler:list_products', name='products-list')
許可するhttpのメソッドを指定することができます。
指定していないメソッドの場合、HTTPMethodNotAllowed(405)となります。
ただ、webapp2のhandler側の実装として、def getのみ実装した場合に、postリクエストが来ると、同様に405になります。
無駄にhandlerを呼び出さないというメリットはあるかもしれません。
ちなみに、僕の場合は、デフォルトでpostリクエストの場合には、共通handlerを作成して、def getを呼び出すようにしており、postの挙動を変えたいたい時のみ、def postを実装しています。
このようなケースで、postのみ許可したくなる場合には、使える機能ですね。
以下は、公式サイトのサンプルソースです。
webapp2.Route(r'/products', handler='handlers.ProductsHandler', name='products-list', methods=['GET'])
httpのスキーマを、httpsまたは、httpのみに制限したい場合に使用する機能です。
以下は、公式サイトのサンプルソースです。
webapp2.Route(r'/products', handler='handlers.ProductsHandler', name='products-list', schemes=['https'])
マッチしなかった場合のエラーは発生せず、無視されるようです。
httpとhttpsで別々のhandlerを呼び出したい場合などは、別々に定義することで対応ができます。
マッチするものが無かった場合には、webapp2デフォルトの動きである、404を返します。
webapp2では、ドメイン、サブドメインを判定する機能があります。
同じリクエストURIでも、ドメインによって呼び出すhandlerを変更したりすることができます。
以下は、公式サイトのサンプルソースです。
サンプルでは、GAEのドメインである、appspot.comをサンプルに使用しています。
import webapp2
from webapp2_extras import routes
app = webapp2.WSGIApplication([
routes.DomainRoute('.app-id.appspot.com'.app-id.appspot.com', [
webapp2.Route('/', handler=SubdomainHomeHandler, name='subdomain-home'),
]),
webapp2.Route('/', handler=HomeHandler, name='home'),
])
上記の例では、サブドメイン付きのドメインからアクセスが有った場合には、SubdomainHomeHandlerを呼び出すことが出来ます。
は、「The URL template」のときと同様に、**kwagsで、handler側で受け取ることが出来ます。
■Matching only www, or anything except www
以下の様に、各正規表現を使うことで、wwwのみを許可したり、wwwを除外したり、appspotと独自ドメインを両方マッチングしたりと幅広く対応することが出来ます。 (僕自身、正規表現も英語も苦手なので、詳細は控えておきます。スミマセン。)
routes.DomainRoute('www.mydomain.com', [
webapp2.Route('/', handler=HomeHandler, name='home',
])
routes.DomainRoute(r''<subdomain:(?!www\.)[^.]+>.mydomain.com'.mydomain.com', [
webapp2.Route('/', handler=HomeHandler, name='home'),
])
routes.DomainRoute(r'<:(app-id\.appspot\.com|www\.mydomain\.com)>', [
webapp2.Route('/', handler=HomeHandler, name='home'),
])
routes.DomainRoute(r'<subdomain:(?!www)[^.]+>.<:(app-id\.appspot\.com|mydomain\.com)>', [
webapp2.Route('/', handler=HomeHandler, name='home'),
])