引き続き、「作ればわかる! Google App Engine for Java プログラミング」本にてPythonを修行中。
今回は、「アバター旅行記」について。
ただ、さすがに参考書1冊だけで Google App Engine が組めるようになるとは思わないので、以下の書籍を追加購入。*1
- 作者: Dan Sanderson,玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/01/24
- メディア: 大型本
- 購入: 5人 クリック: 414回
- この商品を含むブログ (27件) を見る
■環境
- Windows7 x64
- Google App Engine SDK for Python 1.7.1 - 2012-08-21
■Pythonで悩んだところと参考ページ
文字列と日付の変換
- 文字列→日付:datetime.strptime
- 日付→文字列:datetimeオブジェクト.strftime
参考:プログラマでいたい - Pythonで文字列とdatetimeの変換
オーバーロードとオーバーライド
何かを宣言するわけではない模様。C#とは大きく違うので戸惑った。
参考(pdf注意):同志社大学大学院 生命医科学研究科 生命医科学専攻 医工学コース 医療情報システム研究室 - 第3回 Pythonオブジェクト指向ゼミ
DOM解析の方法
xml.dom.minidom をimportして使う(Google App EngineでもOK)。
今回は、初回のphotoタグ情報を取得するときに使用。forで回してreturnという形はいいんだろうか。
参考:Python 2.7ja1 documentation - 19.7. xml.dom.minidom ― 軽量な DOM 実装
def fetch(self, keywords): url = self.build_search_url(keywords) result = urlfetch.fetch(url) dom = minidom.parseString(result.content) photos = dom.getElementsByTagName("photo") for photo in photos: self.farm = photo.getAttribute("farm") self.server = photo.getAttribute("server") self.id = photo.getAttribute("id") self.secret = photo.getAttribute("secret") self.owner = photo.getAttribute("owner") return
URIエンコードの方法
urllibをimportして使う(Google App EngineでもOK)。
参考:
- はてなグループ Python - PythonでURIエンコードするには
- #8 - urllib2.quote()ってアリなんだ
- stackoverflow - Should I use urllib or urllib2?
encodedKeywords = urllib2.quote(keywords.encode('utf-8'))
文字列の連結
URLを構築するため、見やすさを優先し、加算演算子(+)ではなくC#のStringBuilderみたいな方法を探す。
リストで作ってjoin()がよいらしい。
HDEラボ - Python文字列バッファいろいろ 〜一番速い奴連れてこいシリーズ〜
def get_page_url(self): builder = [] builder.append('http://www.flickr.com/') builder.append(self.owner) builder.append('/') builder.append(self.id) url = ''.join(builder) return url
Javaのstaticブロックみたいなものは?
p183にて、staticブロックでavatarのインスタンスを取得しているが、Pythonではどうするのかを調べてみたところ、関数でインスタンスを取得しているところがあったので、今回はそちらを採用。
Ubuntu Forums - Python: Is there official static initializer?
また、デコレータで戻り値を変数に入れるやり方が分からなかったので、デコレータは使用せず。
ただ、これがPythonの書き方かどうかは、正直わからない。
def get_avatar_instances(): return [ EriAvatar(), SounAvatar(), O2Avatar()] class Avatar(object): @staticmethod def get_avatar(avatarId): instances = get_avatar_instances() for instance in instances: if instance.id == avatarId: return instance @staticmethod def get_avatars(): return get_avatar_instances()
stackoverflowにも似たようなものがあったが、今回はインスタンスを作成せずに使うので見送り。
stackoverflow - Is there static block in function in python
■Flickrまわり
■Google App Engine で悩んだところと参考ページ
親クラスのIDをどのように採番するか?
「作ればわかる!」によると、Java版では自動採番することができる模様(p151より)。
一方、Pythonには自動採番する機能が見当たらない。
色々と考えたが、独自の採番クラスを持たせることに落ち着いた。
子クラスの主キーをどうするか?
自動採番は難しい&面倒なことから、単純にタイムスタンプを主キーにしようかとも思ったが、Jobが同時に走ったときに記事が登録されないため、自動的なKeyとした。
親クラスに子クラスをどのように保持するか?
「作ればわかる!」によると、Java版では独自クラス型をリストとして持つことができる模様(p159より)。
一方、Pythonでは、独自クラスでのlistは無理(?)。
item_type はリスト内のアイテムの型(Python 型かクラス)です。リスト値のすべてのアイテムが指定した型である必要があります。item_type はデータストアのいずれかの値の型にする必要があり、list にすることはできません。上記のデータストアの値の型をご覧ください。
一方で、子クラスでReferencePropertyを使えば、親クラスより、collection_name・modelname_set などで子クラスへアクセスできる模様*2。
よって、「親クラスがlistで子クラスを持つ」は不要と判断した。
なお、クラス間で親子関係を表現する方法については、以下に3パターンの記載あり。参考になりました。
トランザクションを使うか?
blogやarticleやblog_idなどを同時に更新することがあるため、トランザクションを使ったほうが良い。
ただ、今回はアバター旅行記をPythonで作るということをメインにしたため、トランザクションはまたあとで。
blogを10件、降順で取得
orderで-した後、fetch(10)とする。
どこで件数を絞るかが最初わからなかった。
q = db.Query(blogs.Blog) q.order("-departureDate") results = q.fetch(10)
Google Developers - Google App Engine Query_fetch
Djangoの各種タグ
公式リファレンスの日本語訳が参考になった。あと、タグの意味とか動作とか。
■フォルダ構成とソースについて
さすがに今回はソースコードが多すぎるので、すべてGitHubのChap5を参照。
GitHub - thinkAmi / 9784798123028_GAE
結構おなかいっぱいなのですが、残りの章がまだまだあるので、次は何を学べるのか楽しみ。
*1:英語版は2nd EditionがEarly Releaseとして出ている模様
*2:「プログラミング Google App Engine」であれば、p202あたり