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

「作ればわかる! Google App Engine for Java プログラミング」本をPythonで書いてみる (10)

Python GoogleAppEngine

引き続き、「作ればわかる! Google App Engine for Java プログラミング」本にてPythonを修行中。


今回は、最後の章の「みんなでお絵かき」。
ChannelAPIとJavaScriptがメインであったので、JavaScript部分は書籍を見ながら写経する(その分、でき上がりがあまり良くない...)。
なお、過去の復習部分も多くあり、クラスをJSON化するところとかを振り返ることができた。
あとは、ChannelAPIを使って複数ブラウザが同時に更新されるのを見て、単純に感動したり。

■準備

書籍に記載されていた、別ライブラリを以下よりダウンロード。


JSONライセンスについては知らなかったので、以下が参考になった。
オープンソース・ライセンスの談話室 - 邪悪なことに使うなという、JSONライセンスに関する個人的な解釈


json2.jsのライセンスについてはJSONライセンスとパブリックドメインのどちらかは正直分からず。以下にはパブリックドメインとの記載あり。
OLEX - JSON in Javascript



■実装時に困ったことと対応

ChannelAPIまわり

以下を参考にした。


app.yamlへの追加も忘れずに。

inbound_services:
- channel_presence
データストアに、db.Text型をリストで持つプロパティを用意するには

item_typeに指定してあげればよい。
別内容だが、今回は絵の描き始めに空のリストを入れてあげる必要があったため、default=Noneを設定して空のリストを入れられるようにもした。

strokes = db.ListProperty(item_type=db.Text, default=None)

参考:Google Developers - Google App Engine - 型とプロパティ クラス - class ListProperty(item_type, verbose_name=None, default=None, ...)


ちなみに、2つの線が途切れている図をデータストアに格納すると、プロパティの中身は以下のようになった。2つの要素(「u」始まり)のリストであることが見て取れる。

[u"[{\\"x\\":124,\\"y\\":145},{\\"x\\":127,\\"y\\":145},{\\"x\\":128,\\"y\\":145},{\\"x\\":130,\\"y\\":145},{\\"x\\":133,\\"y\\":145},{\\"x\\":134,\\"y\\":145},{\\"x\\":138,\\"y\\":145},{\\"x\\":147,\\"y\\":145},{\\"x\\":153,\\"y\\":147},{\\"x\\":155,\\"y\\":148}]", u"[{\\"x\\":216,\\"y\\":165},{\\"x\\":216,\\"y\\":167},{\\"x\\":216,\\"y\\":168},{\\"x\\":218,\\"y\\":170},{\\"x\\":221,\\"y\\":171},{\\"x\\":224,\\"y\\":171},{\\"x\\":233,\\"y\\":174},{\\"x\\":241,\\"y\\":175},{\\"x\\":250,\\"y\\":175},{\\"x\\":253,\\"y\\":175}]"]

db.Text型のリストへ、[]で囲まれた文字列を要素として追加するには

リストなので[]で囲まれており、普通に渡してしまうと文字列でなく配列として認識されてしまう。
そこで明確に文字列であることを分かるように設定した。(strでも良かったかも)

picture.strokes.append(db.Text(unicode(stroke)))
picture.put()
データストアのlistプロパティをforで回したいとき

変数に移動することなく、以下の形で回すことができた。

for stroke in pictures.strokes:
    strokes.append(stroke)
データストアのlistに要素を追加したいとき

エンティティを取得した後に、listへappendする。

picture.strokes.append(db.Text(unicode(stroke)))
取得する全数が不定な時の、iterableな結果の取得方法

RPCオブジェクトを使って、run()で取得する。

rpc = db.create_rpc(deadline=10, read_policy=db.EVENTUAL_CONSISTENCY)
return Picture.all().run(rpc=rpc)

参考:Google Developers - Google App Engine - Query クラス



iterableかどうかを知りたい時

今回は使用していないが、RPCオブジェクトとiterableまわりで知りたくなったため調べてみたところ、以下が参考になった。
Stringでなければ、hasattr(オブジェクト, '__iter__')でOKということで。
A-LIAISON BLOG - Pythonで変数の型をチェックする方法(Javaでいうinstanceofが使いたい)



データストアのIDを取得するには

取得するとき

Picture.get_by_id(int(id))

使うとき

picture.key().id()
Pythonオーバーロード

無いので、メソッド名を別にして利用する。


datetime型を「yyyy年mm月DD日 HH時MM分ごろの絵」という文字列へと変換する

datetime.strftime('%Y年%m月%d日 %H時%M分ごろの絵')とやりたかったが、Unicodeが渡せなさそうなので、断念。
datetiem.yearなどを地道に拾って連結する形にした(改行して見やすくするため、両端をカッコで囲った)。

self.__createDate = ( unicode(jst.year) + u'年'
                    + unicode(jst.month) + u'月'
                    + unicode(jst.day) + u'日 '
                    + unicode(jst.hour) + u'時'
                    + unicode(jst.minute) + u'分ごろの絵' )

参考:pythonで心理実験 - 例題12-3:ビジランスの実験(試作)



ソースコード

GitHubのchap11として追加。




今回ですべてのアプリを実装し終わりました。
ゆっくりとした進み具合でしたが、PythonGoogle App Engineの入門となりました。
知ったことの量が多かったので、忘れないようにどこかでまとめようかとは思います。