Google App Engine で JSON 出力

海外のブログを見ていたら,こんな記述をみつけました。

GAE doesn’t include ‘simplejson‘ in the Python container so you are going to have to include it with your application. I downloaded simplejson-1.8.1 and symbolically linked its simplejson directory into my application directory.

そんなことないですよね。 simplejson パッケージが django.utils に含まれているので,次のようにすれば JSON 形式で出力することができます。日本語文字列を含む場合は, ensure_ascii=False とするところがポイント。

# -*- coding: utf-8 -*-
import wsgiref.handlers
from django.utils import simplejson
from google.appengine.ext import webapp

class hoge(webapp.RequestHandler):
    data = {"cancam_models": [{"name": u"蛯原友里", "age": 28},
                              {"name": u"徳澤直子", "age": 23},
                              {"name": u"西山茉希", "age": 22},]}
    self.response.content_type = “application/json”
    simplejson.dump(data, self.response.out, ensure_ascii=False)

また,最後の行を次のようにすると,JSONP 形式で出力できます。

self.response.out.write("%s(%s)" %
    (callback, simplejson.dumps(data, ensure_ascii=False)))


関連リンク:
simplejson - Google Code

conky

バッテリー駆動時には使いませんが。

Fedora や CentOS でRPMのアップデート情報をメール通知する

Fedora や CentOS などパッケージ管理に yum を使っているディストリビューションで,アップデートパッケージがあることをメールで通知するには, /etc/yum/yum-updatesd.conf を編集します。
emit_via = dbus はデスクトップ用の設定なので email に変更し, run_interval と updaterefresh を適当な間隔に変更します。

[main]
# how often to check for new updates (in seconds)
run_interval = 86400
# how often to allow checking on request (in seconds)
updaterefresh = 3600

# how to send notifications (valid: dbus, email, syslog)
emit_via = email

デフォルトでは, 通知メールの From: と To: はそれぞれ root になっているので,変更したい場合は次の設定を追加します。

email_to = root@example.com
email_from = yum-updatesd@example.com

設定が完了したら,忘れずにサービスを再起動。

# /sbin/service yum-updatesd reload

設定した宛先に下記のようなメールが送られてくれば成功です。

Subject: yum: 1 Updates Available (on example)
From: yum-updatesd@example.com
To: root@example.com

Hi,
This is the automatic update system on example.
There are 1 package updates available. Please run the system updater.

Packages available for update:
    traceroute.x86_64        3:2.0.10-1.fc8         updates

Thank You,
Your Computer

はずなんだけど,うまく動かない…
yum-updatesd は各所で評判が悪いみたいなので,後でソースを見ることにして, yum-cron をインストールします。

# yum install yum-cron

デフォルトだと勝手にパッケージをアップデートしてしまうので,チェックを行うだけにします。 /etc/sysconfig/yum-cron を編集。

# Don't install, just check (valid: yes|no)
CHECK_ONLY=yes

サービスを自動起動するように設定して完了。

# /sbin/chkconfig yum-cron on
# /sbin/service yum-cron start
夜間 yum 更新の有効化中:                                   [  OK  ]

アップデートパッケージがある場合は, Cron Daemon から送られてくるメールに次のようなメッセージが表示されるようになりました。

/etc/cron.daily/yum.cron:

New updates available for host example

traceroute.x86_64            3:2.0.10-1.fc8         updates

伊豆・修善寺

伊豆・修善寺に行ってきました。本当は,友人たちと天城山に登ろうとしたのですが,生憎の天候により登山は断念して修善寺温泉に立ち寄ることに。5月の修善寺は,新緑がとても綺麗で,朝一のためほぼ貸切の温泉に入って思いっきり癒されてきました。
帰りがけに御殿場から見た富士山もとても綺麗でした。

Tokko foot spa Shuzenji Izu
Fresh green ojizou-sama
Shuzenji Map Mt. Fuji in Japan

it's cafe : 下高井戸の無線LANが使えるカフェ

it's cafe は,下高井戸から歩いて1分のところにあるカフェです。フリーランスとして記事やプログラムを書く仕事をしていると,たまに気分を変えて違う場所で作業したいと思うときが多々あります。そんな時に it's cafe は,無線LANが無料で使えるのでおすすめ。ランチや夜ご飯セットもあるのでお腹が空いてもOK。

このカフェのオーナー,実は以前一緒に仕事をしていたのですが,エントランスをキャンバスにしたり,寄席を開いたり,いろいろ面白い企画をしています。女性客が多いというのもその人柄を見れば,うなずける気がします。それから,まだオーナーに確認していないのですが, Weboo! Returns. を見たと言えば,僕も ThinkPad に貼っている右のステッカーがもらえます!(いいですよね?)もらえます!


it's cafe[イッツ・カフェ]
- 東京都杉並区下高井戸1-2-14 1F
- open 12:00 / close 22:30 (L.O.21:30)
- ランチ 12:00 - 15:00
- 定休日:毎週水曜日

View Larger Map

Google App Engine で1対多の結合をする

話題の Google App Engine ですが,やはり人気のようでまだアカウントが取得できていない人も多いようですね。アカウントがなくても,ローカルで開発は始められるので,これから始めようと思っている人は次の記事を参考にすると良いと思います(手前味噌ですが…)。

» 一番かんたんなGoogle App Engineの使い方 |gihyo.jp (技術評論社)

さて,本題の Google App Engine で1対多のジョインを行う方法に入っていきましょう。「BigTable」をバックエンドに利用できる Google App Engine ですが, RDBMS の考え方に慣れているとけっこう戸惑うことが多いです。 SQL に似た専用の GQL 言語は, OR や != が使えなかったりしてとても癖があります。親レコードと子レコードを JOIN する方法もわからずに最初は悩んだのですが,モデルを定義する際の ReferenceProperty に collection_name を定義しておくことで簡単にできます。正確には結合ではないかもしれませんが,親レコードから collection_name プロパティを参照することで関連する 子レコードのみを抽出することができるようになります。

以下のコードがそのサンプルになります。

# -*- coding: utf-8 -*-
import os,cgi
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template

class Group(db.Model):
    name = db.StringProperty(required=True)
    
class Person(db.Model):
    name = db.StringProperty(required=True)
    age = db.IntegerProperty(required=True)
    group = db.ReferenceProperty(Group, 
        required=True, collection_name='members')

class MainPage(webapp.RequestHandler):
    def get(self):
        # Group data
        group1 = Group(name="Perfume")
        group1.put()
        group2 = Group(name="Puffy")
        group2.put()

        # Person data
        person1 = Person(name=u"大本 彩乃", age=19, group=group1)
        person1.put()
        person2 = Person(name=u"樫野 有香", age=19, group=group1)
        person2.put()
        person3 = Person(name=u"西脇 綾香", age=19, group=group1)
        person3.put()
        person4 = Person(name=u"大貫 亜美", age=34, group=group2)
        person4.put()
        person5 = Person(name=u"吉村 由美", age=33, group=group2)
        person5.put()

        groups = Group.all()
        
        path = os.path.join(os.path.dirname(__file__), 'example.html')
        self.response.out.write(template.render(path, {'groups': groups}))

def main():
    application = webapp.WSGIApplication(
        [('/', MainPage)],
        debug=True)
    wsgiref.handlers.CGIHandler().run(application)
        
if __name__ == "__main__":
    main()

アイドルがグループに所属するというモデルを考えます。大貫亜美さんと吉村由美さんは Puffy というグループに所属します。また,大本彩乃さん,樫野有香さん,西脇綾香さんは Perfume というグループに所属します。上のコードだと, Group と Person というモデルを定義して, MainPage クラスでデータを登録しています。そして, groups という変数に全てのグループを格納して,テンプレートに渡しています。

そして表示に利用するテンプレートは,これです。 Group ごとにループ処理を行い,さらにそのグループに所属するメンバーでループ処理を行っています。

  {% for group in groups %}
     <h2>{{ group.name }}</h2>
     <ul>
     {% for member in group.members %}
       <li>{{ member.name }} ({{ member.age }}歳)</li>
     {% endfor %}
     </ul>
  {% endfor %}

以上のプログラムを実行した結果は,次のようになります。

ちゃんと,グループごとに分かれて表示されていますね。