<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>taichino.com &#187; google app engine</title>
	<atom:link href="http://taichino.com/tag/google-app-engine/feed" rel="self" type="application/rss+xml" />
	<link>http://taichino.com</link>
	<description>永遠のネバーランド</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:33:04 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Cookpadの開発コンテスト24に「ごはんソムリエ」で参加した</title>
		<link>http://taichino.com/daily-life/1729</link>
		<comments>http://taichino.com/daily-life/1729#comments</comments>
		<pubDate>Sat, 24 Apr 2010 15:03:18 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[生活記録]]></category>
		<category><![CDATA[24contest]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ごはんソムリエ]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1729</guid>
		<description><![CDATA[今日のweb界隈はCookpadの開発コンテスト24の話題で盛り上がっていた訳ですが、僕もギリギリ応募しました。タイトルは「ごはんソムリエ」です。ごはんソムリエはCookpadのレシピから和・洋・中から食べたいものを選択するだけで、主菜・副菜・汁物をバランスよく提示するサービスです。まとめて材料も表示するので買い物時も便利です。 課題は「朝起きてから学校や会社に行くまでの時間をより便利にするためには」でした。僕は朝やっといたら１日がちょっと楽しくなる事をテーマにしようと思いまして、夕飯の献立を楽に作りたいと思いました。実際僕も夕飯を作るの役割がアサインされておりまして、どうしようとモヤモヤしながら１日が過ぎて、結局スーパーに行ってから作った事のあるものでお茶を濁すパターンが多い訳です。 一方、朝の内に献立が決まると、作り手は１日気持ちよく過ごせますし、食べる役のパートナーやお子様も今日の献立を朝のうちに伝えられる事で、夕飯を楽しみに１日を過ごせる訳です。もしかしたら浮気も減るかもしれませんYO！ と言う訳で、張り切って作り始めたわけですが、実際は予定の半分も実装できなくてorzです。現状では画面もぐちゃぐちゃで酷いですw でも出さないよりはましだと信じて出しました。ぼちぼちアップデートして育てていこうと思います。 以下は、反省などです。 まず自分の24時間の使い方は以下です。 21:00〜21:30 課題の確認とアイデア出し。=> 思いつかないので寝た。 21:30〜06:30 睡眠。前日がほぼ徹夜だったので、如何ともしがたい。 06:30〜07:30 アイデア出し。この時点ではiPhoneから使うTODOアプリにするつもりだった。 07:30〜09:00 TODOアプリの仕様策定 09:00〜10:00 TODOアプリの設計。その結果とてもじゃ無いけど１日で終わらないと判断。TODOアプリはボツに。 10:00〜11:00 再度アイデア出し。ごはんソムリエに決定。 11:00〜12:00 仕様策定と設計。 12:00〜13:30 実生活側で問題発生して対応 13:30〜14:00 設計の続き 14:00〜14:30 場所移動 14:30〜17:00 プログラミング 17:00〜17:30 場所移動 17:30〜20:30 プログラミング 20:30〜21:00 画面作成と応募 可視化すると以下になります。寝すぎなのと、没作業がもったいないですね。 なおアウトプット量は以下です。少ないw これでも必死だったとか恥ずかしすぎます。 Python: 343 line HTMLとCSS: 200 line 画像 : 4 点 でも良い指標になりました。現状でPythonでWebサービスだと特に詰まらなくても１時間あたり100行書けないと言う事ですね。 まとめ 今回よかった点 技術的なチャレンジは一切入れなかった。結果的に殆どハマらなかった。 当初から仕様を70%程度削ったけど、応募までこぎつけた。別に応募しなくても良いんじゃね？って何度思ったか。でも今回諦めたら、次も諦めてしまうに違いないと思って踏ん張った。 今回よくなかった点 [...]]]></description>
			<content:encoded><![CDATA[<p>今日のweb界隈は<a href="http://info.cookpad.com/24contest">Cookpadの開発コンテスト24</a>の話題で盛り上がっていた訳ですが、僕もギリギリ応募しました。タイトルは「<a href="http://healthy-menu.appspot.com/sommelier/">ごはんソムリエ</a>」です。ごはんソムリエはCookpadのレシピから和・洋・中から食べたいものを選択するだけで、主菜・副菜・汁物をバランスよく提示するサービスです。まとめて材料も表示するので買い物時も便利です。</p>
<p><a href="http://taichino.com/wp-content/uploads/2010/04/Picture-34.png"><img src="http://taichino.com/wp-content/uploads/2010/04/Picture-34-300x159.png" alt="ごはんソムリエ 画面キャプチャ" title="ごはんソムリエ 画面キャプチャ" width="300" height="159" class="alignnone size-medium wp-image-1732" /></a></p>
<p><span id="more-1729"></span></p>
<p>課題は「朝起きてから学校や会社に行くまでの時間をより便利にするためには」でした。僕は朝やっといたら１日がちょっと楽しくなる事をテーマにしようと思いまして、夕飯の献立を楽に作りたいと思いました。実際僕も夕飯を作るの役割がアサインされておりまして、どうしようとモヤモヤしながら１日が過ぎて、結局スーパーに行ってから作った事のあるものでお茶を濁すパターンが多い訳です。</p>
<p>一方、朝の内に献立が決まると、作り手は１日気持ちよく過ごせますし、食べる役のパートナーやお子様も今日の献立を朝のうちに伝えられる事で、夕飯を楽しみに１日を過ごせる訳です。もしかしたら浮気も減るかもしれませんYO！</p>
<p>と言う訳で、張り切って作り始めたわけですが、実際は予定の半分も実装できなくてorzです。現状では画面もぐちゃぐちゃで酷いですw でも出さないよりはましだと信じて出しました。ぼちぼちアップデートして育てていこうと思います。</p>
<p>以下は、反省などです。</p>
<p>まず自分の24時間の使い方は以下です。</p>
<table>
<tr>
<td width="100px">21:00〜21:30</td>
<td> 課題の確認とアイデア出し。=> 思いつかないので寝た。</td>
</tr>
<tr>
<td width="100px">21:30〜06:30</td>
<td> 睡眠。前日がほぼ徹夜だったので、如何ともしがたい。</td>
</tr>
<tr>
<td width="100px">06:30〜07:30</td>
<td> アイデア出し。この時点ではiPhoneから使うTODOアプリにするつもりだった。</td>
</tr>
<tr>
<td width="100px">07:30〜09:00</td>
<td> TODOアプリの仕様策定</td>
</tr>
<tr>
<td width="100px">09:00〜10:00</td>
<td> TODOアプリの設計。その結果とてもじゃ無いけど１日で終わらないと判断。TODOアプリはボツに。</td>
</tr>
<tr>
<td width="100px">10:00〜11:00</td>
<td> 再度アイデア出し。ごはんソムリエに決定。</td>
</tr>
<tr>
<td width="100px">11:00〜12:00</td>
<td> 仕様策定と設計。</td>
</tr>
<tr>
<td width="100px">12:00〜13:30</td>
<td> 実生活側で問題発生して対応</td>
</tr>
<tr>
<td width="100px">13:30〜14:00</td>
<td> 設計の続き</td>
</tr>
<tr>
<td width="100px">14:00〜14:30</td>
<td> 場所移動</td>
</tr>
<tr>
<td width="100px">14:30〜17:00</td>
<td> プログラミング</td>
</tr>
<tr>
<td width="100px">17:00〜17:30</td>
<td> 場所移動</td>
</tr>
<tr>
<td width="100px">17:30〜20:30</td>
<td> プログラミング</td>
</tr>
<tr>
<td width="100px">20:30〜21:00</td>
<td> 画面作成と応募</td>
</tr>
</table>
<p>可視化すると以下になります。寝すぎなのと、没作業がもったいないですね。<br />
<div id="attachment_1734" class="wp-caption alignnone" style="width: 375px"><a href="http://taichino.com/wp-content/uploads/2010/04/Picture-33.png"><img src="http://taichino.com/wp-content/uploads/2010/04/Picture-33.png" alt="24開発コンテストの時間の使い方 円グラフ" title="24開発コンテストの時間の使い方" width="365" height="197" class="size-full wp-image-1734" /></a><p class="wp-caption-text">24開発コンテストの時間の使い方 円グラフ</p></div></p>
<p>なおアウトプット量は以下です。少ないw これでも必死だったとか恥ずかしすぎます。</p>
<ul>
<li>Python: 343 line</li>
<li>HTMLとCSS: 200 line</li>
<li>画像 : 4 点</li>
</ul>
<p>でも良い指標になりました。現状でPythonでWebサービスだと特に詰まらなくても１時間あたり100行書けないと言う事ですね。</p>
<h4><strong>まとめ</strong></h4>
<ul>
<li>
	<strong>今回よかった点</strong></p>
<ul>
<li>技術的なチャレンジは一切入れなかった。結果的に殆どハマらなかった。</li>
<li>
		当初から仕様を70%程度削ったけど、応募までこぎつけた。別に応募しなくても良いんじゃね？って何度思ったか。でも今回諦めたら、次も諦めてしまうに違いないと思って踏ん張った。
	  </li>
</ul>
</li>
<li>
	<strong>今回よくなかった点</strong></p>
<ul>
<li>コンディションが良くなかった。前日徹夜とかは無い。</li>
<li>アイデアを途中で変えた。短時間コンテストで無駄作業を作ると痛い。</li>
<li>無駄になった仕様や設計がたくさんある。意識したのにまだ大風呂敷広げてた。</li>
</ul>
</li>
<li>
	<strong>今回気付いた点</strong></p>
<ul>
<li>
		時間が限られるとアイデアが非常に重要だと言う事がわかった。限られた時間で何が出来るかという視点は、普段からもう少し意識しても良いなぁと思った。
	  </li>
<li>
		画像を作るのと、プログラムを書くのは直ぐに切り替えられない。タスクスイッチでどうしても能率が下がった。次があればデザイン屋さんと組んで出てみたい。
	  </li>
</ul>
</li>
</ul>
<p>なんだかんだ言って面白かったので、次回があればまた参加したいと思います。最後に機会を作って下さったCookpadの皆様に感謝します。ありがとうございました。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/daily-life/1729/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GAE上ではジェネレータを保存出来なかった話</title>
		<link>http://taichino.com/programming/1666</link>
		<comments>http://taichino.com/programming/1666#comments</comments>
		<pubDate>Tue, 30 Mar 2010 13:05:23 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[generator_tools]]></category>
		<category><![CDATA[google app engine]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1666</guid>
		<description><![CDATA[先日ジェネレータを一旦保存しておいて、途中から再実行するというエントリを書きました。これで何がしたかったかと言うと、この方法を使うとリクエストあたりの30秒制限があるGAEでも、割と綺麗に擬似的な無限ループが表現出来るだろうと言う事で実験していました。もっと言えばGAEでクローラを作りたかった訳ですが、残念ながら出来ませんでしたという話です。 まず僕が書きたかったのは以下の様なコードです。かなり単純ですがクローラの様な雰囲気ですね。本来はrunが無限ループ的に実行されていて、dispatcherとhandlerを繰り返し呼ぶ感じだと思いますが、ここでは簡単のためdispatcherをジェネレータにして、handlerは省略しています。これでrunを繰り返しcron等で呼び出す事で、擬似的に無限ループを表現できますね。保存用に変数等を用意していないのが好ましいと思います。 from generator_tools import loads, dumps &#160; def get_dispatcher&#40;&#41;: links = get_some_links&#40;&#41; while len&#40;links&#41; &#62; 0: yield links.pop&#40;&#41; &#160; def run&#40;&#41;: cache = memcache.get&#40;'dispatcher'&#41; dispatcher = cache and loads&#40;cache&#41; or get_dispatcher&#40;fetch&#41; try: while True: link = dispatcher.next&#40;&#41; crawl_link&#40;link&#41; except DeadlineExceededError: memcache.add&#40;'dispatcher', dumps&#40;dispatcher&#41;&#41; or memcache.replace&#40;'dispatcher', dumps&#40;dispatcher&#41;&#41; return HttpResponse&#40;'success to run'&#41; しかしこのコードは残念ながらGAEの本番環境上では動きません。上記コードを実行すると、generator_tools.loadsの呼出しで、RuntimeError: cannot create code objects [...]]]></description>
			<content:encoded><![CDATA[<p>先日<a href="http://taichino.com/programming/1657">ジェネレータを一旦保存しておいて、途中から再実行するというエントリ</a>を書きました。これで何がしたかったかと言うと、この方法を使うとリクエストあたりの30秒制限があるGAEでも、割と綺麗に擬似的な無限ループが表現出来るだろうと言う事で実験していました。もっと言えばGAEでクローラを作りたかった訳ですが、残念ながら出来ませんでしたという話です。</p>
<p><span id="more-1666"></span></p>
<p>まず僕が書きたかったのは以下の様なコードです。かなり単純ですがクローラの様な雰囲気ですね。本来はrunが無限ループ的に実行されていて、dispatcherとhandlerを繰り返し呼ぶ感じだと思いますが、ここでは簡単のためdispatcherをジェネレータにして、handlerは省略しています。これでrunを繰り返しcron等で呼び出す事で、擬似的に無限ループを表現できますね。保存用に変数等を用意していないのが好ましいと思います。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> generator_tools <span style="color: #ff7700;font-weight:bold;">import</span> loads, dumps
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_dispatcher<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  links = get_some_links<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>links<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
    <span style="color: #ff7700;font-weight:bold;">yield</span> links.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  cache = memcache.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'dispatcher'</span><span style="color: black;">&#41;</span>
  dispatcher = cache <span style="color: #ff7700;font-weight:bold;">and</span> loads<span style="color: black;">&#40;</span>cache<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> get_dispatcher<span style="color: black;">&#40;</span>fetch<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
  	  link = dispatcher.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	  crawl_link<span style="color: black;">&#40;</span>link<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span> DeadlineExceededError:
    memcache.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'dispatcher'</span>, dumps<span style="color: black;">&#40;</span>dispatcher<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> memcache.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'dispatcher'</span>, dumps<span style="color: black;">&#40;</span>dispatcher<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span><span style="color: #483d8b;">'success to run'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>しかしこのコードは残念ながら<strong>GAEの本番環境上では動きません</strong>。上記コードを実行すると、generator_tools.loadsの呼出しで、RuntimeError: cannot create code objects in restricted execution modeというエラーがでます。どういう事か調べてみると、generator_toolsはジェネレータを保存する時に、自身のopコードを文字列に変換します。その文字列で表されたopコードを元に実行コードを復元する訳ですが、その復元処理がセキュリティ上の問題から禁止されているようです。まぁ考えてみると当たり前の制限なんですが残念です。ちなみに開発環境では問題なく動作するので注意が必要です。開発環境で書き上げたコードがボツになったので，僕はショックで１日現実逃避しました。</p>
<p>なお上記のget_dispatcherしたジェネレータをgenerator_tools.dumpsすると以下の様な文字列になります。Pythonのopコード(の文字列表現)初めて見ましたが、割と単純でJavaVMのより読み易い印象ですね。</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">ccopy_reg
_reconstructor
p0
(cgenerator_tools.picklegenerators
SnapshotEnvelope
p1
c__builtin__
object
p2
Ntp3
Rp4
(dp5
S'obj'
p6
g0
&nbsp;
# 長いので以下省略</pre></div></div>

<p>前回のエントリで面白い事が出来るかもと言ったのは、この疑似無限ループのことで、他の使い方は思いつかないので、別に面白い事は出来ませんでした。ちゃんちゃん。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1666/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>tweepyでtwitterの3-legged OAuth認証を試してみた(GoogleAppEngine)</title>
		<link>http://taichino.com/programming/1433</link>
		<comments>http://taichino.com/programming/1433#comments</comments>
		<pubDate>Mon, 28 Dec 2009 04:13:34 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[tweepy]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1433</guid>
		<description><![CDATA[そろそろGAE上でユーザ登録が必要なサービスを作りたいのですが、ユーザ登録周りの実装はやりたくないので、twitterのOAuthを代わりに使ってみる事にしました。twitterのAPIを叩くのにこれまではtwythonを使っていたのですが，OAuthに対応していなかったので、今回はtweepyを使います。以前2-legged OAuthを試してみましたが、今回は3-legged OAuthです。 twitterのOAuth認証によるログイン、ログアウトとログイン後にユーザのタイムライン表示と、tweetを実装しています。ロジックのソースは以下になりますが、まず動作しているサンプルを見るのが早いと思います。 # -*- coding: utf-8 -*- &#160; import os import cgi import logging &#160; from google.appengine.ext.webapp import template from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db import wsgiref.handlers &#160; from google.appengine.api import memcache import uuid import tweepy from simple_cookie2 import Cookies &#160; CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET [...]]]></description>
			<content:encoded><![CDATA[<p>そろそろGAE上でユーザ登録が必要なサービスを作りたいのですが、ユーザ登録周りの実装はやりたくないので、twitterのOAuthを代わりに使ってみる事にしました。twitterのAPIを叩くのにこれまではtwythonを使っていたのですが，OAuthに対応していなかったので、今回はtweepyを使います。<a href="http://taichino.com/programming/1057">以前2-legged OAuthを試してみました</a>が、今回は3-legged OAuthです。</p>
<p><span id="more-1433"></span></p>
<p>twitterのOAuth認証によるログイン、ログアウトとログイン後にユーザのタイムライン表示と、tweetを実装しています。ロジックのソースは以下になりますが、まず<a href="http://7.latest.taichino.appspot.com/">動作しているサンプル</a>を見るのが早いと思います。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">cgi</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span>.<span style="color: black;">webapp</span> <span style="color: #ff7700;font-weight:bold;">import</span> template
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span> <span style="color: #ff7700;font-weight:bold;">import</span> webapp
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span>.<span style="color: black;">webapp</span>.<span style="color: black;">util</span> <span style="color: #ff7700;font-weight:bold;">import</span> run_wsgi_app
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span> <span style="color: #ff7700;font-weight:bold;">import</span> db
<span style="color: #ff7700;font-weight:bold;">import</span> wsgiref.<span style="color: black;">handlers</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> memcache 
<span style="color: #ff7700;font-weight:bold;">import</span> uuid
<span style="color: #ff7700;font-weight:bold;">import</span> tweepy
<span style="color: #ff7700;font-weight:bold;">from</span> simple_cookie2 <span style="color: #ff7700;font-weight:bold;">import</span> Cookies
&nbsp;
CONSUMER_KEY    = <span style="color: #483d8b;">'your consumer key'</span>
CONSUMER_SECRET = <span style="color: #483d8b;">'your consumer secret'</span>
CALLBACK_URL    = <span style="color: #483d8b;">'http://127.0.0.1:8080/oauth_cb'</span>
SESSION_EXPIRE  = <span style="color: #ff4500;">300</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># ユーザがtwitter認証を行う際のリクエストトークンを保持するモデル</span>
<span style="color: #ff7700;font-weight:bold;">class</span> RequestToken<span style="color: black;">&#40;</span>db.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
  token_key    = db.<span style="color: black;">StringProperty</span><span style="color: black;">&#40;</span>required=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
  token_secret = db.<span style="color: black;">StringProperty</span><span style="color: black;">&#40;</span>required=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># ログインしている場合はタイムライン表示</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Home<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, max_age=SESSION_EXPIRE<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> cookie.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#41;</span>:
      cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span> = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># セッション開始</span>
&nbsp;
    <span style="color: black;">&#40;</span>timeline, username<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span><span style="color: #008000;">None</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
    access_token = memcache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> access_token:
      auth = tweepy.<span style="color: black;">OAuthHandler</span><span style="color: black;">&#40;</span>CONSUMER_KEY, CONSUMER_SECRET<span style="color: black;">&#41;</span>
      auth.<span style="color: black;">set_access_token</span><span style="color: black;">&#40;</span>access_token.<span style="color: black;">key</span>, access_token.<span style="color: black;">secret</span><span style="color: black;">&#41;</span>
      username = auth.<span style="color: black;">get_username</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
      api = tweepy.<span style="color: black;">API</span><span style="color: black;">&#40;</span>auth_handler=auth<span style="color: black;">&#41;</span>
      timeline = api.<span style="color: black;">home_timeline</span><span style="color: black;">&#40;</span>count=<span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">response</span>.<span style="color: black;">out</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>template.<span style="color: black;">render</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'timeline.html'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'username'</span>:username, <span style="color: #483d8b;">'timeline'</span>: timeline<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># tweet</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Update<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> post<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
    access_token = memcache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> access_token:
      auth = tweepy.<span style="color: black;">OAuthHandler</span><span style="color: black;">&#40;</span>CONSUMER_KEY, CONSUMER_SECRET<span style="color: black;">&#41;</span>
      auth.<span style="color: black;">set_access_token</span><span style="color: black;">&#40;</span>access_token.<span style="color: black;">key</span>, access_token.<span style="color: black;">secret</span><span style="color: black;">&#41;</span>
      api = tweepy.<span style="color: black;">API</span><span style="color: black;">&#40;</span>auth_handler=auth<span style="color: black;">&#41;</span>
      api.<span style="color: black;">update_status</span><span style="color: black;">&#40;</span>status=<span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'status'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">redirect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># twitterのOAuth認証</span>
<span style="color: #ff7700;font-weight:bold;">class</span> OAuth<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    auth = tweepy.<span style="color: black;">OAuthHandler</span><span style="color: black;">&#40;</span>CONSUMER_KEY, CONSUMER_SECRET, CALLBACK_URL<span style="color: black;">&#41;</span>
    auth_url = auth.<span style="color: black;">get_authorization_url</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    request_token = RequestToken<span style="color: black;">&#40;</span>token_key=auth.<span style="color: black;">request_token</span>.<span style="color: black;">key</span>, token_secret=auth.<span style="color: black;">request_token</span>.<span style="color: black;">secret</span><span style="color: black;">&#41;</span>
    request_token.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">redirect</span><span style="color: black;">&#40;</span>auth_url<span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># twitterの認証画面へリダイレクト</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># twitterのOAuth認証後のコールバック</span>
<span style="color: #ff7700;font-weight:bold;">class</span> OAuthCB<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    request_token_key = <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;oauth_token&quot;</span><span style="color: black;">&#41;</span>
    request_verifier  = <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'oauth_verifier'</span><span style="color: black;">&#41;</span>
    auth = tweepy.<span style="color: black;">OAuthHandler</span><span style="color: black;">&#40;</span>CONSUMER_KEY, CONSUMER_SECRET<span style="color: black;">&#41;</span>
    request_token = RequestToken.<span style="color: black;">gql</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;WHERE token_key=:1&quot;</span>, request_token_key<span style="color: black;">&#41;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    auth.<span style="color: black;">set_request_token</span><span style="color: black;">&#40;</span>request_token.<span style="color: black;">token_key</span>, request_token.<span style="color: black;">token_secret</span><span style="color: black;">&#41;</span>
    access_token = auth.<span style="color: black;">get_access_token</span><span style="color: black;">&#40;</span>request_verifier<span style="color: black;">&#41;</span>
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
    memcache.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span>, access_token, SESSION_EXPIRE<span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">redirect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># ログアウト</span>
<span style="color: #808080; font-style: italic;"># twitter認証側のCookieはいじれないのでセッションを削除する</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Logout<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> cookie.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#41;</span>:
      memcache.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">del</span> cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">redirect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
&nbsp;
application = webapp.<span style="color: black;">WSGIApplication</span><span style="color: black;">&#40;</span>
  <span style="color: black;">&#91;</span>
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span>, Home<span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'/update'</span>, Update<span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'/logout'</span>,   Logout<span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'/oauth'</span>,    OAuth<span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'/oauth_cb'</span>, OAuthCB<span style="color: black;">&#41;</span>,
  <span style="color: black;">&#93;</span>,
  debug=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
  run_wsgi_app<span style="color: black;">&#40;</span>application<span style="color: black;">&#41;</span></pre></div></div>

<p>少しややこしいですね。tweepyはよく作られたライブラリなので、一度ソースを読んでみる事をお薦めしますが、OAuth認証が必要なtwitter apiを使う場合の処理シーケンスをおおざっぱに言うと、以下のようになります。</p>
<ol>
<li>tweepy.OAuthHandlerにConsumerKey、ConsumerSecret, RequestToken, ユーザの認証を示すVerifierを食わせてaccess tokenを得る</li>
<li>tweepy.APIを作成する際に1のOAuthHandlerを食わせて、認証済みAPIオブジェクトを作成する</li>
<li>認証済みAPIオブジェクトを使って各種API呼出しを行う</li>
</ol>
<p>access tokenがあれば認証済みOAuthHandlerを再構築できるので，僕はセッションIDをキーにaccess tokenをmemcacheに保存しています。<a href="http://www.atmarkit.co.jp/fsecurity/special/106oauth/oauth01.html">@ITの入門記事</a>や<a href="http://oauth.net/core/1.0/">oauthの仕様</a>と見比べながら読むと理解が早いかもしれません。</p>
<p>またセッション周りについては<a href="http://taichino.com/programming/1424">先ほどの記事</a>のsimple_cookieを使用しています。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1433/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>webappでcookieを使う(GoogleAppEngine)</title>
		<link>http://taichino.com/programming/1424</link>
		<comments>http://taichino.com/programming/1424#comments</comments>
		<pubDate>Mon, 28 Dec 2009 02:44:12 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[google app engine]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1424</guid>
		<description><![CDATA[GoogleAppEngineで何かを作る時はapp-engine-patchを使っているのですが、ちょっとした実験等をする時はやっぱりwebappが手軽です。今回はセッションの実験をしたかったのですが、webappにはセッションを扱う仕組みがないので、自前でCookie周りの処理をしようと思ったら、Cookieを扱うライブラリも標準ではありませんでした。いやでも流石にCookieくらいはだれか書いてるだろうという事で調べてみたら、GoogleAppEngineのオンラインCookbookに記事が見つかりました。 この記事のソースコードを適当に保存して(僕はsimple_cookie.py)、以下のようにして使用します。このクラスを使うと辞書と同じ感覚でCookieを扱えます。Cookiesのコンストラクタでmax_ageを指定する事で、セッションの期限も決める事ができます。以下は簡単なログインとログアウトの例です。 from simple_cookie import Cookies &#160; class Login&#40;webapp.RequestHandler&#41;: def get&#40;self&#41;: cookie = Cookies&#40;self, max_age=300&#41; if not cookie.has_key&#40;'sid'&#41;: cookie&#91;'sid'&#93; = str&#40;uuid.uuid4&#40;&#41;&#41; # ５分間維持するセッションID作成 &#160; sid = cookie&#91;'sid'&#93; username = memcache.get&#40;sid&#41; &#160; # do something with session &#160; class Logout&#40;webapp.RequestHandler&#41;: def get&#40;self&#41;: cookie = Cookies&#40;self, max_age=300&#41; if cookie.has_key&#40;'sid'&#41;: memcache.remove&#40;cookie&#91;'sid'&#93;&#41; del cookie&#91;'sid'&#93; # セッションの削除 これでwebappでもセッションやCookieが扱えるようになりましたね。]]></description>
			<content:encoded><![CDATA[<p>GoogleAppEngineで何かを作る時はapp-engine-patchを使っているのですが、ちょっとした実験等をする時はやっぱりwebappが手軽です。今回はセッションの実験をしたかったのですが、webappにはセッションを扱う仕組みがないので、自前でCookie周りの処理をしようと思ったら、Cookieを扱うライブラリも標準ではありませんでした。いやでも流石にCookieくらいはだれか書いてるだろうという事で調べてみたら、GoogleAppEngineの<a href="http://appengine-cookbook.appspot.com/recipe/a-simple-cookie-class/" class="broken_link">オンラインCookbookに記事</a>が見つかりました。</p>
<p><span id="more-1424"></span></p>
<p><a href="http://appengine-cookbook.appspot.com/recipe/a-simple-cookie-class/" class="broken_link">この記事</a>のソースコードを適当に保存して(僕はsimple_cookie.py)、以下のようにして使用します。このクラスを使うと辞書と同じ感覚でCookieを扱えます。Cookiesのコンストラクタでmax_ageを指定する事で、セッションの期限も決める事ができます。以下は簡単なログインとログアウトの例です。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> simple_cookie <span style="color: #ff7700;font-weight:bold;">import</span> Cookies
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Login<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, max_age=<span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> cookie.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#41;</span>:
      cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span> = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># ５分間維持するセッションID作成</span>
&nbsp;
	sid = cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span>
	username = memcache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>sid<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># do something with session</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Logout<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    cookie = Cookies<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, max_age=<span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> cookie.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#41;</span>:
      memcache.<span style="color: black;">remove</span><span style="color: black;">&#40;</span>cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
      <span style="color: #ff7700;font-weight:bold;">del</span> cookie<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sid'</span><span style="color: black;">&#93;</span>  <span style="color: #808080; font-style: italic;"># セッションの削除</span></pre></div></div>

<p>これでwebappでもセッションやCookieが扱えるようになりましたね。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1424/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google App Engineでイチローウォッチャー作ってみた</title>
		<link>http://taichino.com/programming/849</link>
		<comments>http://taichino.com/programming/849#comments</comments>
		<pubDate>Mon, 24 Aug 2009 21:13:40 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[google app engine]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=849</guid>
		<description><![CDATA[ここ１ヶ月半くらいGoogle App Engineを弄っている訳ですが、練習でイチローウォッチャーというサイトを作りました。イチローの試合結果を集めて、グラフで可視化する簡単なアプリな訳ですが、結構長く掛かってしまいました。 開発環境はGAE + Django(app-engine-patch) + as3です。 せっかくなので遅まきではありますが、Google App Engineについて気付いた点を列挙してみました。ちなみに僕はpythonもDjangoも今回初めて触りました。php + cakeからの移民になります。 python (2.5.x) 内包表記が便利すぎる ソース整形時にインデントがずれて発生するバグがストレスフル インクリメント、デクリメントが無いなんて。。 __init__.pyが存在するディレクトリがパッケージになる。。 公式リファレンスが読みにくい (サンプルが少ない) pdbはデバッグコードが必要なのが残念 辞書の展開とJSONの相性良すぎ Google App Engine 無料でしかも安定してる 管理ページが充実してる datastore RDBに対するアクセスよりも重い 本番サーバのデータを削除するのが面倒 フェッチあたり1000件の縛りがやっぱり面倒 集約関数とgroup byが無いのが残念すぎる flashとはpyamfを使って通信 lxmlが使えない。結果的にxpathが使えない Django(app-engine-patch) adminインタフェースが使える scafoldはない GAEへの依存度を減らせる Djangoのテンプレートは今まで見た中で一番良い Djangoの慣習がよく出来ていて、プロジェクト全体が整理される Djangoの習得コストはそんなに安くない(結局１ヶ月くらいかかった) バックエンドがRDBで無い等、確かにGAEは色々制約は強いですが、それでも現状では個人や小さな企業にとって最良のホスティングサービスだと思います。GAEを使えるようになっていれば、サーバ運用のコストは劇的に下がります。個人的に考えているのは、その結果としてクライアントサイド開発の際にも手軽にサーバとの連携を視野に入れる事が出来ると言う事です。これはGAEを覚えたかった一番の理由で、これからiPhone等のクライアントアプリ開発に絡めていこうと思っています。 またFlashを使えばGAEの制約をある程度は緩和できそうです。現状ではGAEだけで全てを処理するのは難しいですが、GAEをシステムの中心に据えて、サブシステムと連携させていく事で、面白い物が作れそうな、そんな気がします。]]></description>
			<content:encoded><![CDATA[<p>ここ１ヶ月半くらいGoogle App Engineを弄っている訳ですが、練習で<a href="http://mlb-stats.appspot.com/iw/">イチローウォッチャー</a>というサイトを作りました。イチローの試合結果を集めて、グラフで可視化する簡単なアプリな訳ですが、結構長く掛かってしまいました。</p>
<p><span id="more-849"></span></p>
<p><a href="http://mlb-stats.appspot.com/iw/" ><img src="http://taichino.com/wp-content/uploads/2009/08/Picture-6.png" /> </a></p>
<p>開発環境はGAE + Django(app-engine-patch) + as3です。<br />
せっかくなので遅まきではありますが、Google App Engineについて気付いた点を列挙してみました。ちなみに僕はpythonもDjangoも今回初めて触りました。php + cakeからの移民になります。</p>
<p><strong>python (2.5.x)</strong></p>
<ul>
<li>内包表記が便利すぎる</li>
<li>ソース整形時にインデントがずれて発生するバグがストレスフル</li>
<li>インクリメント、デクリメントが無いなんて。。</li>
<li>__init__.pyが存在するディレクトリがパッケージになる。。</li>
<li>公式リファレンスが読みにくい (サンプルが少ない)</li>
<li>pdbはデバッグコードが必要なのが残念</li>
<li>辞書の展開とJSONの相性良すぎ</li>
</ul>
<p><strong>Google App Engine</strong></p>
<ul>
<li>無料でしかも安定してる</li>
<li>管理ページが充実してる</li>
<li>
datastore</p>
<ul>
<li>RDBに対するアクセスよりも重い</li>
<li>本番サーバのデータを削除するのが面倒</li>
<li>フェッチあたり1000件の縛りがやっぱり面倒</li>
<li>集約関数とgroup byが無いのが残念すぎる</li>
</ul>
</li>
<li>flashとはpyamfを使って通信</li>
<li>lxmlが使えない。結果的にxpathが使えない</li>
</ul>
<p><strong>Django(app-engine-patch)</strong></p>
<ul>
<li>adminインタフェースが使える</li>
<li>scafoldはない</li>
<li>GAEへの依存度を減らせる</li>
<li>Djangoのテンプレートは今まで見た中で一番良い</li>
<li>Djangoの慣習がよく出来ていて、プロジェクト全体が整理される</li>
<li>Djangoの習得コストはそんなに安くない(結局１ヶ月くらいかかった)</li>
</ul>
<p>バックエンドがRDBで無い等、確かにGAEは色々制約は強いですが、それでも現状では個人や小さな企業にとって最良のホスティングサービスだと思います。GAEを使えるようになっていれば、サーバ運用のコストは劇的に下がります。個人的に考えているのは、その結果としてクライアントサイド開発の際にも手軽にサーバとの連携を視野に入れる事が出来ると言う事です。これはGAEを覚えたかった一番の理由で、これからiPhone等のクライアントアプリ開発に絡めていこうと思っています。</p>
<p>またFlashを使えばGAEの制約をある程度は緩和できそうです。現状ではGAEだけで全てを処理するのは難しいですが、GAEをシステムの中心に据えて、サブシステムと連携させていく事で、面白い物が作れそうな、そんな気がします。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/849/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.878 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-09 19:23:56 -->

