Lvx ex Cælis虛實相歸,有無相生;寒暑相反,明晦相隨。2008-07-23T14:30:19-04:00Habaritag:blog.bcse.info,2008-07-23:atom/f8c9ba7ecda48300f580919587b856d385726c62URL Routing in GAEOBCSEEATItag:blog.bcse.info,2008:url-routing-in-gaeo/12167228152008-07-22T18:06:22-04:002008-07-22T18:06:22-04:00<p>GAEO 預設有幾種繞徑方式,<a href="http://code.google.com/p/google-app-engine-oil/wiki/UrlRouting">官方文件</a>如是說:</p><ol><li><code>/</code> 代表呼叫 <code>{'controller':'welcome', 'action':'index'}</code></li><li><code>/foo/bar</code> 代表呼叫 <code>{'controller':'foo', 'action': 'bar'}</code></li><li><code>/foo</code> 代表呼叫 <code>{'controller':'foo', 'action':'index'}</code></li></ol><p>如果你也是用 <code>gaeogen.py</code> 產生出基本架構的話,那就還有:</p><ol><li><code>/foo/bar/blah</code> 代表呼叫 <code>{'controller':'foo', 'action': 'bar', 'id': 'blah'}</code></li></ol><p>官方文件中的範例跟使用 <code>gaeogen.py</code> 產生出的架構相同,但沒有說要怎麼取得 Controller 、 Action 和 ID ,在下對於 Python 不熟,所以又是試了一段時間才成功。</p><p>Controller 應該不用再次介紹,用 <code>gaeogen.py</code> 產生出來便是。Action 是指 Controller 中的 function 名稱,舉例來說, <code>index</code> 就是一個 Action 。</p><pre class="prettyprint"><code>class MyController(BaseController):<br /> def index(self): # 我就是 Action 啦!<br /> pass</code></pre><p>接下來的問題是要怎麼取得 ID ,我 trace 原始碼 trace 了很久(因為我是新手嘛!),才知道原來用 <code>self.params.get('id')</code> 便能取得。此外也可以用 <code>self.params['id']</code> ,但這個方法在沒有 ID 時會發生錯誤。以下給一份完整的範例,此範例的用途是將Yahoo!奇摩字典的 Auto-completion 轉換為 Firefox 可用的 OpenSearch Suggestions 格式。</p><pre class="prettyprint"><code>import cgi<br />from gaeo.controller import BaseController<br />from google.appengine.api import urlfetch<br /><br />class YdictController(BaseController):<br /> def index(self):<br /> pass<br /><br /> def lookup(self):<br /> p = cgi.escape(self.params['id']) if 'id' in self.params else ''<br /> try:<br /> result = urlfetch.fetch('http://ws.dict.tpe.yahoo.com/suggest_data.php?of=js&p=' + p, method="GET")<br /> if result.status_code == 200 and result.content.startswith('fxsearch([') and result.content.endswith('])'):<br /> suggestions = result.content[9:-1]<br /> self.render(text=suggestions)<br /> except:<br /> pass</code></pre><p>成果:<a href="http://bcse.appspot.com/ydict/lookup/sugges">http://bcse.appspot.com/ydict/lookup/sugges</a></p><p>等我試出來後,突然想到了什麼,便去查 RoR 的文件…… 果不其然,這取用方法跟 RoR 好像啊~ 看來在 GAEO 缺乏文件的現在,或許也能先參考 RoR 的文件…… XD</p>Writing <code>Model</code> on GAEOBCSEEATItag:blog.bcse.info,2008:writing-code-model-code-on-gaeo/12167225462008-07-22T06:31:24-04:002008-07-22T06:31:24-04:00<p>大概只有像我這樣的 Python 超新手才會有這個問題 XD</p><p>在 GAEO 中建立 Model 的流程如下:</p><ol><li>在 <code>application</code> 資料夾中新增一個 <code>model</code> 資料夾</li><li>在 <code>model</code> 資料夾中新增兩個檔案 <code>__init__.py</code> 、 <code>my_model.py</code></li><li><p><code>__init__.py</code> 保持空白就可以,在 <code>my_model.py</code> 中則可以寫你要的 Model,舉例如下:</p><pre class="prettyprint"><code>from google.appengine.ext import db<br />from gaeo.model import BaseModel<br /># 本範例中沒用到 BaseModel 新增的功能,所以也可刪去這行<br /><br />class User(BaseModel): # 如果不用 BaseModel,就必須改為繼承 db.Model<br /> user = db.UserProperty(required=True)<br /> nickname = db.StringProperty(required=True)<br /> email = db.EmailProperty(required=True)</code></pre></li><li><p>接下來重點來了!在 <code>my_controller.py</code> 中要怎麼引用這個 Model 呢?</p><pre class="prettyprint"><code>from model import my_model</code></pre></li></ol><hr /><p>順便筆記一下遍歷的方法</p><pre class="prettyprint"><code>users = my_model.User.all()<br /># 我覺得既然用了 DataStore (BigTable),就不要再用 GQL 作查詢<br /># 實際上這種寫法也比較容易閱讀<br />for user in users:<br /> print user.nickname</code></pre>My First Step toward Google App Engine / PythonBCSEEATItag:blog.bcse.info,2008:my-first-step-toward-google-app-engine-python/12167218242008-07-22T06:27:39-04:002008-07-22T06:27:39-04:00<p>雖然放假了,我還是滿常來 Lab 的,這兩天的主要內容是研究 Google App Engine ,進度從安裝、「<a href="http://en.wikipedia.org/wiki/Hello_world_program">Hello World!</a>」、以 Google Account 作身分認證,一直到使用 Datastore API ,然後上 PTT 發現有人把功能很完整的 Ikariam 物資交易平台做好了,讓我又失去了我的題目<sup id="fnref:my-first-step-toward-google-app-engine-python-4"><a href="#fn:my-first-step-toward-google-app-engine-python-4" rel="footnote">1</a></sup> XD</p><p>雖然如此,但作一下最近的筆記。</p><h3>安裝 Python 、 Google App Engine 及 GAEO</h3><ol><li>下載 <a href="http://code.google.com/appengine/downloads.html">Google App Engine SDK</a> 及 <a href="http://www.python.org/download/">Python 2.5</a>。</li><li>以上兩個都是照著指示按「下一步」就能裝好。</li><li>下載 <a href="http://code.google.com/p/google-app-engine-oil/">GAEO</a>,然後解壓縮到任何你喜歡的地方。</li><li>在我的電腦上按右鍵→內容→進階→環境變數。然後在 PATH 的最後加上 <code>;C:\Python25;D:\Documents\htdocs\gaeo\bin</code> ←此為範例,請根據你將 Python 、 GAEO 安裝在哪裡而修改。至於 Google App Engine SDK 則會自動幫你加上,不用我們動手。</li></ol><h3>建立一個新的專案</h3><ol><li>在你喜歡的資料夾中,以命令提示字元執行 <code>gaeo.py project_name</code> ,GAEO 就會幫你建立好 <code>project_name</code> 資料夾以及基本的程式與資料夾結構。</li><li>然後在 <code>project_name</code> 資料夾中,以命令提示字元執行 <code>dev_appserver.py --port=8080 .</code> <sup id="fnref:my-first-step-toward-google-app-engine-python-1"><a href="#fn:my-first-step-toward-google-app-engine-python-1" rel="footnote">2</a></sup>,這樣就能將程式執行起來,你可以在 http://127.0.0.1:8080/ 看到結果,看見 “It works!!” 就表示成功了。這個畫面的程式位於 <code>project_name/application/controller/welcome.py</code> ,而 template 位於 <code>project_name/application/templates/welcome</code> 資料夾中。</li></ol><h3>建立新的 Controller</h3><ol><li>在 <code>project_name</code> 資料夾中,以命令提示字元執行 <code>gaeogen.py controller Say</code> 這樣會在 <code>project_name/application/controller</code> 中建立一個 <code>say.py</code> ,其中就是新的 Controller ,名為 <code>SayController</code> ;此外也會建立一個 <code>project_name/application/templates/say</code> 資料夾,內容是空的,留待未來使用。</li></ol><h3>上傳到 Google App Engine</h3><ol><li>這邊我實在得說 Google 包裝得很好,只要在 <code>project_name</code> 資料夾中,以命令提示字元執行 <code>appcfg.py update .</code><sup id="fnref:my-first-step-toward-google-app-engine-python-2"><a href="#fn:my-first-step-toward-google-app-engine-python-2" rel="footnote">3</a></sup> ,程式便會傳上去,並且會自動編版號。</li></ol><h3>其他</h3><ol><li>以 Google Account 作身分認證同樣很簡單,基本上照著 Google 的教學文件作就沒錯了,只不過在本機端測試時它不需要真的登入,只會出現一個看起來怪怪的登入畫面,這並不是你作錯了。</li><li>有時候程式發生問題時,會噴 Error 404 而不給錯誤訊息,我目前還不知道 Python 有什麼簡單的 debug 方式…</li><li>目前 GAEO 的 <code>gaeogen.py</code> 只能用來生成 Controller ,所以我不知道 Model 應該放在哪裡…</li><li>在編輯工具方面我試了 Eclipse 及 UliPad , Eclipse 看得出來是一個功能非常強大的 IDE ,<del>但我不知道怎麼將它和 GAEO 整合在一起</del><sup id="fnref:my-first-step-toward-google-app-engine-python-3"><a href="#fn:my-first-step-toward-google-app-engine-python-3" rel="footnote">4</a></sup>;而 UliPad 有些功能不符合我的習慣,它的 Auto-completion 則是基於「本檔案中曾使用過的函式」,對我來說沒什麼幫助,最後還是用回 EmEditor。</li></ol><div class="footnotes"><hr /><ol><li id="fn:my-first-step-toward-google-app-engine-python-4"><p>我本來是想做一個類似拍賣的網站來練習,不過主要目的其實還是想玩 GAE <a href="#fnref:my-first-step-toward-google-app-engine-python-4" rev="footnote">↩</a></p></li><li id="fn:my-first-step-toward-google-app-engine-python-1"><p>我將這段儲存為 <code>run.bat</code> ,這樣執行比較方便。 <a href="#fnref:my-first-step-toward-google-app-engine-python-1" rev="footnote">↩</a></p></li><li id="fn:my-first-step-toward-google-app-engine-python-2"><p>我將這段儲存為 <code>update.bat</code> ,這樣執行比較方便。 <a href="#fnref:my-first-step-toward-google-app-engine-python-2" rev="footnote">↩</a></p></li><li id="fn:my-first-step-toward-google-app-engine-python-3"><p>用 <code>gaeo.py --eclipse project_name</code> 就可以囉! <a href="#fnref:my-first-step-toward-google-app-engine-python-3" rev="footnote">↩</a></p><p></li></p><p></ol></div></p>Image Expander 0.3.2BCSEEATItag:blog.bcse.info,2008:image-expander-0-3-2/12135832782008-06-15T22:40:06-04:002008-06-15T22:40:06-04:00<p>請到<a href="http://blog.bcse.info/image-expander">原文</a>安裝新版。</p><p>原來要用 JavaScript 檢驗圖片是否存在,根本不需用到 XHR ,用 image 物件本身的 <code>onload</code>/<code>onerror</code> 事件就可以了。所以我將 Image Expander 的 XHR 拿掉,程式碼變得簡單許多,還解決了 Cross-Domain 問題,讓我們一起來贊美舊時代吧! XD</p>Jaiku Plugin for HabariBCSEEATItag:blog.bcse.info,2008:jaiku-plugin-for-habari/12126052422008-06-09T22:12:19-04:002008-06-09T22:12:19-04:00<h4>簡介</h4><p>此 Plugin 讓你在 blog 上顯示你的 Jaiku 最新動態。</p><h4>安裝</h4><ol><li>解壓縮檔案。</li><li>將 jaiku 資料夾放到 /user/plugins 資料夾中,然後到 Habari 管理介面中啟用它。</li><li><p>將下面這行貼到你的 Theme 中。</p><pre class="prettyprint"><code><?php if ( Plugins::is_loaded('Jaiku') ) $theme->jaiku(); ?></code></pre></li></ol><h4>設定 / 自訂</h4><p>啟用後,請按下 <strong>Configure</strong> 來設定此 Plugin ,有這些項目需要輸入:</p><ul><li><strong>Jaiku username</strong> – 你在 Jaiku 的使用者名稱/帳號。</li><li><strong>Presences to show</strong> – 設定要顯示幾個 presences 。</li><li><strong>Cache expiry in seconds</strong> – 設定暫存檔保存多久,單位是秒。</li></ul><p>如果你要修改 HTML 呈現的結果,可以將 jaiku.php 複製到你的 Theme 資料夾中並修改這個檔案。</p><h4>下載</h4><p>如果你的 Habari 版本為 r1946 以上,請使用 0.2 版,否則請使用 0.1.1 版。</p><div class="download"><a href="http://bcse.googlecode.com/files/habarijaiku-v0.1.1.tar.gz">Jaiku 0.1.1</a> Habari r1943 以下適用</div><div class="download"><a href="http://bcse.googlecode.com/files/habarijaiku-0.3.tar.gz">Jaiku 0.3</a> Habari r1946 以上適用</div><h4>更新紀錄</h4><ul><li><strong>0.3</strong> (2008-06-10) – 可設定要顯示幾個 presences 。</li><li><strong>0.2.1</strong> (2008-06-09) – 檢驗使用者輸入的資料是否正確。</li><li><strong>0.2</strong> (2008-06-04) – 更新為新的 FormUI 的寫法。</li><li><strong>0.1.1</strong> (2008-06-04) – 移除一些不必要的程式碼。</li><li><strong>0.1</strong> (2008-05-29) – 初次釋出。</li></ul><hr /><h4>Introduction</h4><p>This plugin show your latest presences on your blog.</p><h4>Installation</h4><ol><li>Extract the file.</li><li>Put the folder ‘jaiku’ to /user/plugins and activate it.</li><li><p>Copy and paste the following line to your theme.</p><pre class="prettyprint"><code><?php if ( Plugins::is_loaded('Jaiku') ) $theme->jaiku(); ?></code></pre></li></ol><h4>Configuration & Customization</h4><p>After activated it, click <strong>Configure</strong> button to setup the plugin.</p><ul><li><strong>Jaiku username</strong> – Place your Jaiku username here.</li><li><strong>Presences to show</strong> – Number of presences to show.</li><li><strong>Cache expiry in seconds</strong> – Number of second after the call that the cache will expire.</li></ul><p>You can copy ‘jaiku.php’ to your theme directory and modify the HTML output.</p><h4>Download</h4><p>Only use version 0.2 if you are using Habari r1946 or higher.</p><div class="download"><a href="http://bcse.googlecode.com/files/habarijaiku-v0.1.1.tar.gz">Jaiku 0.1.1</a> for Habari r1943 or lower</div><div class="download"><a href="http://bcse.googlecode.com/files/habarijaiku-0.3.tar.gz">Jaiku 0.3</a> for Habari r1946 or higher</div><h4>Changelog</h4><ul><li><strong>0.3</strong> (2008-06-10) – Now you can show multiple presences.</li><li><strong>0.2.1</strong> (2008-06-09) – Validate user inputs.</li><li><strong>0.2</strong> (2008-06-04) – Updated to work with the new FormUI.</li><li><strong>0.1.1</strong> (2008-06-04) – Remove some unnecessary functions.</li><li><strong>0.1</strong> (2008-05-29) – Initial release.</li></ul>Image ExpanderBCSEEATItag:blog.bcse.info,2008:image-expander/12118113762008-06-15T22:36:59-04:002008-06-15T22:36:59-04:00<p><a href="http://userscripts.org/scripts/show/27359">Image Expander</a> 的靈感來自於 gslin 的 <a href="http://blog.gslin.org/archives/2007/09/15/1313/">Wretch Album Expander</a> 。</p><p>最近實在愈來愈懶,所以寫了這個 script 來讓我少點幾次滑鼠 :p 它的功能是將縮圖替換為原圖,判斷方法為:</p><ol><li>超連結的目標位址為 .jpg、 .jpeg、.png 或 .gif 結尾。</li><li>超連結的內容只有一張圖片,沒有其他物件或文字。</li><li>經由 <code>onload()</code> 確認圖片存在。</li></ol><p>用 HTML 來表示的話,就是像以下架構的縮圖,才會被替換為原圖。</p><pre class="prettyprint"><code><a href="原圖網址"><img src="縮圖網址" /></a></code></pre><p>這個 script 相當容易導致網頁版面被破壞,建議在有需要時才啟動它,平常關掉比較好~</p><div class="download install"><a href="http://userscripts.org/scripts/source/27359.user.js">安裝 Image Expander</a> v0.3.2</div>微軟免費釋出 Meiryo 及微軟雅黑字型BCSEEATItag:blog.bcse.info,2008:-meiryo/12111644672008-07-12T00:55:45-04:002008-07-12T00:55:45-04:00<p>這並不是一篇新聞,只是我剛才發現一個滿有趣的地方…… 在下載 Meiryo 的頁面,若將語言改為「<a href="http://www.microsoft.com/downloads/details.aspx?displaylang=ja-nec&FamilyID=f7d758d2-46ff-4c55-92f2-69ae834ac928">日本語 (NEC)</a>」,就可以跳過 WGA 驗證直接下載 :)</p><p>至於微軟雅黑則在此:<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b15774c0-5b42-48b4-8ba8-9293fdc72099&DisplayLang=zh-cn">Simplified Chinese ClearType fonts for Windows XP</a></p><p>Update: 韓文的 <a href="http://www.microsoft.com/downloads/details.aspx?familyid=C55A8C2B-B451-4D1F-87F3-690F78342AE8&displaylang=en">Malgun Gothic</a> 也釋出了。</p><p>Update: 繁體中文的<a href="http://www.microsoft.com/downloads/details.aspx?familyid=87E726A9-5C79-4A73-9347-78A557314D0B&displaylang=en">微軟正黑體</a>也釋出了。</p>