GoogleAppEngine再入門(2) -Datastore API 1-

前回:GoogleAppEngine再入門(1) -webapp Framework- - souta-bot log

今回も引き続き日経ソフトウェア2009年1月号特集のPart2でテーマはDatastoreAPI

  • AppEngineはファイルシステムにアクセスできないのでデータの永続化にはDatastore APIを使用する
  • Datastore APIのモジュールはgoogle.appengine.ext.db
  • DatastoreとRDBは微妙に違うらしい

おおまかな流れ

  1. まずModelクラスを継承してデータモデルを作成(RDBのテーブル)
  2. データモデルにpropertyを作成(RDBのカラム)
    1. propertyには型を指定する
  3. entityを作成する(RDBの行)
  4. SQLに似たGQLで問い合わせる

またまたサンプルを写経

# -*- coding: utf-8 -*-
from google.appengine.ext import db, webapp
from google.appengine.ext.webapp.util import run_wsgi_app

#データモデル
class Pet(db.Model):
    #propertyを定義
    name = db.StringProperty(required=True) #文字列型
    pet_type = db.StringProperty(required=True, #required=Trueで省略不可(RDBのnot null)になる
                                 choices=set(["cat", "dog", "bird"])) #入力の制限
    birthdate = db.DateProperty()
    weight_in_pounds = db.IntegerProperty()
    spayed_or_neutered = db.BooleanProperty(default=False) #避妊手術か去勢か

def init_data():
    #all()でQueryオブジェクトを作成、そのfetch(100)でentityを100個取得
    pets = Pet.all().fetch(100)
    #100個のentityを削除
    db.delete(pets)

    bill = Pet(name="Bill", pet_type="dog")
    bill.weight_in_pounds = 24
    bill.put() #Datastoreに格納

    #まとめて格納
    hacker = Pet(name="Hacker", pet_type="dog", weight_in_pounds=24)
    tama = Pet(name="Tama", pet_type="cat", weight_in_pounds=8)
    piko = Pet(name="Piko", pet_type="bird", weight_in_pounds=1)
    db.put([hacker, tama, piko])

class AnimalHandler(webapp.RequestHandler):
    def get(self):
        if self.request.get("init"):
            init_data()

        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
        self.response.out.write("<html><body>")
        #初期化用リンク
        self.response.out.write("<a href='/?init=1'>Initialize data</a><br />")
        self.response.out.write("<table border='1'><tr>\n")
        self.response.out.write("<th>Name</th><th>Type</th><th>Weight</th>")
        self.response.out.write("<th>spayed_or_neutered</th>")

        query = Pet.all()
        pets = query.fetch(4)
        for pet in pets:
            self.response.out.write("<tr><td>%s</td>" % pet.name)
            self.response.out.write("<td>%s</td>" % pet.pet_type)
            self.response.out.write("<td>%s lbs</td>" % pet.weight_in_pounds) #lbsはポンド(質量)の単位 libra(天秤)が語源
            self.response.out.write("<td>%s</td>" % pet.spayed_or_neutered)
            self.response.out.write("</tr>")
        self.response.out.write("</table>")

        self.response.out.write("<form method='POST'>")
        self.response.out.write("<input type='submit' value='Neuter Bill'></form>")
        self.response.out.write("</body></html>")

    #上のフォーム(POSTメソッド)に対応
    def post(self):
        #GQLを実行し、結果をqに入れる
        q = db.GqlQuery("select * from Pet where name = :1 and pet_type = :2",
                        "Bill", "dog")
        #去勢して格納
        for pet in q:
            pet.spayed_or_neutered = True
            pet.put()
        #再表示
        self.redirect("/")

application = webapp.WSGIApplication([('/', AnimalHandler)], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
  • いつものようにapp.yamlのscriptを変更して表示
    • ケアレスミスでブラウザにエラーが大量に表示されたが一番下にエラーの発生箇所があるので修正はラクチン

初期表示

初期化

Billを去勢

(⊃Д`)

次回:GoogleAppEngine再入門(3) -Datastore API 2- - souta-bot log