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

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

GoogleAppEngine Python

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


今回は、「イマココ!」について。
Google App Engineにも少しずつ慣れてきたところで、jQuery。両者の連携で、色々と勉強になりました。

■環境について

バージョンが「1.7.2 - 2012-09-18」に上がったが、動作は問題なさそう。

■本の追記について

公式サイトに追記あり。削除機能を追加したとのこと。今回はこちらも合わせて実装。
「作ればわかる!Google App Engine for Javaプログラミング」公式サイト - 第6章「イマココ!」



■Geolocation API関連

本では「Google Gears APIを使う」とのことだったが、Gears APIは2011/3/11で終了してしまった模様。

With all this now available in HTML5, it’s finally time to say goodbye to Gears. There will be no new Gears releases, and newer browsers such as Firefox 4 and Internet Explorer 9 will not be supported. We will also be removing Gears from Chrome in Chrome 12.
Gears API Blog - Stopping the Gears


Android 2.3.3でもGeolocation APIが使える模様なので、Geolocation APIの方を利用することに。
参考: floatingdays - スマートフォンのGeolocation API 調査メモ


なお、Geolocation APIの精度が高い場合ではどうしても取得できないところがあったため、参考までに精度が低いバージョンもコメントアウトして残しておく(index.js)。
また、緯度・経度を目視で確認できるよう、登録画面には緯度・経度を表示する欄を残しておく(すぐに消えてしまうけれど)。

Google App Engine関連

Modelに独自のIDを持たせるか?

本とは異なり、Pythonではデータストアの内部で管理する主キーを定義しなくてもよいかと思ったが、削除機能の追加に伴い識別するための何かが必要になった。
独自キーを設定するかとも考えたが、エンティティは数値IDを持っているようなので、そちらを利用することにした。
Pythonで遊ぶよ - Google App Engineのkey, id, name, kind, path, entity groupなどについてのまとめ


以下の実装で、getで得たentityIDにて削除できる。

def get(self):
    data = places.Place.get_by_id(long(self.request.get('entityID')))
    data.delete()
ModelでGeolocationを表すにはどうするか?

本のようにlat,lngを分けて持たせるのでもよかったが、ModelにGeoPtProperty()を見つけたので、そちらを利用することに。
JSON化する時の注意点は後述。




JSON関連

Google App EngineでのJSONエンコード

Python2.7ではjsonモジュールが使える(以前はdjangoのものを使っていた模様)とのことだが、GAEのModelが扱えない 。


なお、webapp2にもjsonラッパーが存在するが、内部でjson.dumps()を呼んでいる模様なので、使えない。


実装方法は、以下を参考に必要最低限。[]で囲むのは力技で処理。
stackoverflow - JSON serialization of Google App Engine models

db.GeoPtProperty()のJSON

Pythonの型でないとjson.dumps()はうまく動作しないため、以下を参考に実装。
stackoverflow - Cannot JSON serialize python Appengine GeoModel subclass using simple json

JSONで返す時のヘッダについて

エラーとはならなかったものの、以下の記述に従って、「application/json; charset=utf-8」を与えた。
stackoverflow - jQuery won't parse my JSON from AJAX query

self.response.headers['Content-Type'] = 'application/json;  charset=utf-8'
JSONデータは「'」ではなく「"」で囲む

Pythonはどちらでも可なものの、JSONでは「"」でないとエラーとなるので、注意。
参考:全力で気まぐれ - jQueryのajaxでdataTypeをjsonにしてみたら




jQueryJavaScript関連

jQuery.ajax(options)について

以下のところを参考にoptionsをセット
jQuery日本語リファレンス - jQuery.ajax(options)

前回更新日時の扱いについて

本ではlastDateをgetTime()として1970年1月1日午前0時からのミリ秒を取得・設定していた。
今回はPythonのデータストアとの兼ね合いもあり、Pythonのdatetime型となるように設定した。
ただ、getMonth()は「0〜11」の範囲の値となるため、注意する (それを忘れてハマっていた)。
Mozilla Developer Network - getMonth



Python関連

前回更新日時から「hoge前」へと変換する際、差分はdatetime同士をマイナスすることにより、datetime.delta型で取得可能。
ただし、datetime.delta型はdays,seconds,microsecondsしか持っていないことに注意。
Python 2.7ja1 documentation - 8.1.2. timedelta オブジェクト



■コード

GitHubのChap6へと追加。