Google Code 提供下列語言介面: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
在可擴充的網路應用程式中儲存資料需要一些小技巧。使用者可以在指定時間內,與數十個網頁伺服器進行互動,而且使用者的下一個要求可能會送給不同的網頁伺服器,而不是處理前一個要求的伺服器。所有網頁伺服器需要資料互動,這些資料也是散佈在多部電腦中,而這些電腦也可能位於世界的各個角落。
有了「Google 應用服務引擎」之後,您就不需要擔心上述的這些問題了。「應用服務引擎」的基礎架構會透過簡單的 API 處理資料的散佈、複製以及負載平衡,而您會獲得強大的查詢引擎與交易功能。
這是將問候語儲存在資料存放區的新版 helloworld/helloworld.py。本頁的其他部分討論的是新的功能。
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/sign', Guestbook)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
以此取代 helloworld/helloworld.py,然後在瀏覽器重新載入 http://localhost:8080/。張貼一些訊息以確認訊息已儲存並可正確顯示。
「應用服務引擎」包括 Python Modeling API (Python 模型 API)。它與 Django 的資料模型 API 類似,但它在背景使用「應用服務引擎」的可擴充資料存放區。
在訪客留言板應用程式中,我們希望使用者張貼的訊息可以儲存下來。每則訊息都包括作者的名稱、訊息內容以及訊息張貼的日期及時間, 所以我們可以依照時間順序來顯示訊息。
若要使用 Data Modeling API (資料模型 API),請匯入 google.appengine.ext.db 模組:
from google.appengine.ext import db
以下定義問候語的資料模型:
class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True)
這會以三個屬性來定義 Greeting 模型:author 的值為 User 物件,content 的值是字串,而 date 的值是 datetime.datetime。
部分屬性建構函式接受參數,以進一步設定其行為。若給予 db.StringProperty 建構函式 multiline=True 參數,就表示此屬性值可以包含換行字元。若給予 db.DateTimeProperty 建構函式 auto_now_add=True 參數,會設定模型自動給予新物件建立時的 date (若應用程式沒有另外指定值的話)。如需關於屬性類型及其選項的完整清單,請參閱資料存放區參考。
現在我們已經有了訊息的資料模型,應用程式可以使用模型來建立新的 Greeting 物件,並將它們放入資料存放區。以下新版的 Guestbook 處理常式會建立新的問候語,並將其儲存到資料存放區。
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
這個新的 Guestbook 處理常式會建立新的 Greeting 物件,然後以使用者張貼的資料來設定其 author 和 content 屬性。它不會設定 date 屬性,因此 date 會自動設定為「建立的時間」(如我們設定模型的動作來執行)。
最後,greeting.put() 會將我們的新物件儲存至資料存放區。若我們透過查詢取得此物件,put() 會更新現有的物件。因為我們使用模型建構函式來建立此物件,put() 會將新物件新增到資料存放區。
「應用服務引擎」資料存放區的資料模型有複雜先進的查詢引擎。因為「應用服務引擎」資料存放區不是傳統的關聯式資料庫,所以不會使用 SQL 來指定查詢。而是使用與 SQL 類似的查詢語言來準備查詢,我們稱之為 GQL。GQL 使用類似的語法,提供存取「應用服務引擎」資料存放區查詢引擎的功能。
以下新版的 MainPage 處理常式會查詢資料存放區的問候語:
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
查詢會在這一行發生:
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
或者,您可以呼叫 Greeting 類別的 gql(...) 方法,並省略查詢的 SELECT * FROM Greeting:
greetings = Greeting.gql("ORDER BY date DESC LIMIT 10")
與 SQL 相同,關鍵字 (例如 SELECT) 不分大小寫。不過,名稱會區分大小寫。
因為查詢傳回完整的資料物件,它不會知道如何從模型中只選取特定屬性。所有 GQL 查詢都以 SELECT * FROM model 開頭 (或如同模型 gql(...) 方法所隱含的),因此與 SQL 的語法相同。
GQL 查詢可以使用 WHERE 子句,它可以根據屬性值的一或多個條件來篩選結果集。與 SQL 不同的是,GQL 查詢可能不會包含值常數:GQL 反而會在查詢中對所有值使用參數繫結。例如,只取得目前使用者張貼的訊息:
if users.get_current_user():
greetings = Greeting.gql("WHERE author = :1 ORDER BY date DESC",
users.get_current_user())
您也可以使用具名參數來取代位置參數:
greetings = Greeting.gql("WHERE author = :author ORDER BY date DESC",
author=users.get_current_user())
除了 GQL 之外,Datastore API (資料存放區 API) 提供使用方法來建置查詢物件的其他機制。上述的查詢也可以用下列方式來準備:
greetings = Greeting.all()
greetings.filter("author =", users.get_current_user())
greetings.order("-date")
如需關於 GQL 和查詢 API 的完整描述,請參閱資料存放區參考。
開發網頁伺服器使用本機版本的資料存放區,使用暫存檔案來測試您的應用程式。只要暫存檔存在、資料就會持續存在,而且除非是您要求,否則網頁伺服器就不會重設這些檔案。
若您要開發伺服器在啟動之前刪除其資料存放區,請於啟動伺服器時,使用 --clear_datastore 選項:
dev_appserver.py --clear_datastore helloworld/
我們現在已經有了訪客留言板應用程式,它會驗證使用 Google 帳戶的使用者,讓他們提交訊息,並顯示其他人員留下的訊息。因為「應用服務引擎」會自動處理擴充問題,因此即使我們的應用程式非常受到歡迎,也不需要再回來這裡修改程式碼。
這個最新版本混合了 HTML 內容與 MainPage 處理常式的程式碼,因此我們比較難以變更應用程式的外觀;特別是如果我們的應用程式變得更大、更複雜,就更難以維護。讓我們使用範本來管理外觀,並為 CSS 樣式表使用靜態檔案。
繼續瀏覽「使用範本」一節。