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

引き続き、「作ればわかる! Google App Engine for Java プログラミング」本にてPythonを修行中。
今回は、「アバター旅行記」について。


ただ、さすがに参考書1冊だけで Google App Engine が組めるようになるとは思わないので、以下の書籍を追加購入。*1

プログラミング Google App Engine

プログラミング Google App Engine

■環境

Pythonで悩んだところと参考ページ

switchはどこ?

無い。
参考:Kosei Kitahara's Blog - Pythonでswitch



文字列と日付の変換
  • 文字列→日付: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
文字列の連結

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まわり

FlickrAPIを使うサンプル

以下のコードが参考になりました。
foot mark - AppEngineでFlickr APIを使ってみよう



API内で使う、Flickrライセンスの意味
LICENSE = '1,2,3,4,5,6'

のように使えば良いことはわかったものの、それぞれが何を意味しているのかわからなかったので、調査。

Google App Engine で悩んだところと参考ページ

FlickrGoogleアカウントを使ってもログイン・APIの取得ができる
親クラスのIDをどのように採番するか?

「作ればわかる!」によると、Java版では自動採番することができる模様(p151より)。
一方、Pythonには自動採番する機能が見当たらない。
色々と考えたが、独自の採番クラスを持たせることに落ち着いた。



子クラスの主キーをどうするか?

自動採番は難しい&面倒なことから、単純にタイムスタンプを主キーにしようかとも思ったが、Jobが同時に走ったときに記事が登録されないため、自動的なKeyとした。



親クラスに子クラスをどのように保持するか?

「作ればわかる!」によると、Java版では独自クラス型をリストとして持つことができる模様(p159より)。
一方、Pythonでは、独自クラスでのlistは無理(?)。

item_type はリスト内のアイテムの型(Python 型かクラス)です。リスト値のすべてのアイテムが指定した型である必要があります。item_type はデータストアのいずれかの値の型にする必要があり、list にすることはできません。上記のデータストアの値の型をご覧ください。

Google Developers - Google App Engine ListProperty


一方で、子クラスでReferencePropertyを使えば、親クラスより、collection_name・modelname_set などで子クラスへアクセスできる模様*2

ReferenceProperty は、自動的にモデル インスタンスをプロパティ値として参照、逆参照を行います。

Google Developers - Google App Engine ReferenceProperty


よって、「親クラスがlistで子クラスを持つ」は不要と判断した。


なお、クラス間で親子関係を表現する方法については、以下に3パターンの記載あり。参考になりました。

  1. Webコピペ屋 - Google App Engineでone-to-many(1対多)2kindとReferenceProperty()で
  2. Webコピペ屋 - Google App Engineでone-to-many(1対多)1kindとListProperty()で
  3. Webコピペ屋 - Google App Engineでone-to-many(1対多)2kindとエンティティグループで
トランザクションを使うか?

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あたり