搭配 Python 使用 Cloud Datastore

本頁面的 Bookshelf 應用程式教學課程說明範例應用程式如何將永久資料 (即書籍的中繼資料) 儲存在 Cloud Datastore 中。這個步驟的範例程式碼提供如何對儲存在 Cloud Datastore 中的資料執行建立、讀取、更新及刪除 (CRUD) 作業的範例。

完整的教學課程內容涵蓋了數個頁面的篇幅,本頁面屬於其中一個單元。如要從頭開始及閱讀設定的操作說明,請前往 Python Bookshelf 應用程式

設定

本節使用 2-structured-data 目錄的程式碼。編輯檔案並在此目錄中執行指令。

  1. 開啟 config.py 檔案進行編輯,並替換下列的值:
    • [PROJECT_ID] 的值設為您的專案 ID,您可以在 GCP 主控台中找到專案 ID。
    • [DATA_BACKEND] 的值設定為 datastore
  2. 儲存並關閉 config.py 檔案。

Cloud Datastore 是一套全代管服務,會自動初始化及連線至您的 App Engine 應用程式。

  • 您第一次在專案中使用 Cloud Datastore 時,必須在 GCP 主控台中開啟 Datastore 頁面,並選取 [Datastore Mode] (Datastore 模式) 來初始化服務。您不需要採取進一步的設定。

    前往 Datastore 頁面

  • 安裝依附元件

    如要建立虛擬環境並安裝依附元件,請使用以下指令:

    Linux/macOS

    virtualenv -p python3 env
    source env/bin/activate
    pip install -r requirements.txt
    

    Windows

    virtualenv -p python3 env
    env\scripts\activate
    pip install -r requirements.txt
    

    在本機電腦執行應用程式

    1. 啟動本機網路伺服器:

      python main.py
      
    2. 在瀏覽器中,輸入下列網址:

      [http://localhost:8080](http://localhost:8080){: target="_blank"}
      
    現在,您可以瀏覽應用程式的網頁,並新增、編輯及刪除書籍。

    按下 Ctrl+C 離開工作站,接著離開本機網路伺服器。

    將應用程式部署至 App Engine 彈性環境

    1. 部署範例應用程式:

      gcloud app deploy
      
    2. 在瀏覽器中,輸入下列網址,並將 [YOUR_PROJECT_ID] 替換成您的 GCP 專案 ID:

      https://[YOUR_PROJECT_ID].appspot.com
      

    若您更新了應用程式,您可以輸入部署應用程式時使用的指令來部署更新版本。部署作業會為您的應用程式建立新版本,並將這個新版本晉升為預設版本。應用程式的較舊版本和相關聯的虛擬機器 (VM) 執行個體都會保留下來。這些應用程式版本和 VM 執行個體均屬於計費資源。為減少費用,請刪除應用程式的非預設版本。

    刪除應用程式版本:

    1. 前往 GCP 主控台的「App Engine Versions」(App Engine 版本) 頁面。

      前往版本頁面

    2. 找到您要刪除的非預設應用程式版本,然後點選旁邊的核取方塊。
    3. 按一下頁面頂部的 [刪除] 按鈕, 刪除應用程式版本。

    如要進一步瞭解清除計費資源,請參閱本教學課程最後一個步驟的清除所用資源一節。

    應用程式結構

    Bookshelf 應用程式部署程序與結構

    應用程式會將所有永久資料儲存在 Cloud Datastore。

    瞭解程式碼

    這部分內容會逐步引導您瞭解應用程式程式碼,並說明其運作方式。

    透過表單處理使用者提交內容

    使用者可以透過新增/編輯 HTML 表單的方式,在應用程式中新增及編輯書籍提交內容。

    新增/編輯表單的圖片

    HTML 表單是使用 Flask 的預設範本引擎 Jinja2 (屬於一種 Python 範本引擎) 建立的。以下 Jinja2 範本指定表單包含「Title」(標題)、「Author」(作者)、「Date Published」(發布日期) 和「Description」(描述) 的文字輸入欄位:

    {% extends "base.html" %}
    
    {% block content %}
    <h3>{{action}} book</h3>
    
    <form method="POST" enctype="multipart/form-data">
    
      <div class="form-group">
        <label for="title">Title</label>
        <input type="text" name="title" id="title" value="{{book.title}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="author">Author</label>
        <input type="text" name="author" id="author" value="{{book.author}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="publishedDate">Date Published</label>
        <input type="text" name="publishedDate" id="publishedDate" value="{{book.publishedDate}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="description">Description</label>
        <textarea name="description" id="description" class="form-control">{{book.description}}</textarea>
      </div>
    
      <button type="submit" class="btn btn-success">Save</button>
    </form>
    
    {% endblock %}

    處理表單提交內容

    使用者按一下 [Add book] (新增書籍) 後,crud.add 畫面會顯示表單。使用者填完「Add book」(新增書籍) 表單並按下 [Save] (儲存) 時,系統會在同個畫面上處理表單的 HTTP POST 動作。這個動作會啟動藉由將資料傳遞至 get_model().create 函式,將所提交之資料傳送至 Cloud Datastore 資料庫的流程。

    @crud.route('/add', methods=['GET', 'POST'])
    def add():
        if request.method == 'POST':
            data = request.form.to_dict(flat=True)
    
            book = get_model().create(data)
    
            return redirect(url_for('.view', id=book['id']))
    
        return render_template("form.html", action="Add", book={})

    bookshelf/model_datastore.py 檔案中包含的程式碼會針對 Cloud Datastore 中儲存的資料執行 CRUD 函式。例如,get_model().create 陳述式會呼叫 bookshelf/model_datastore.py 中的 create 函式,該函式會將使用者提交的資料傳送至 update 函式。null 值會傳入第一個參數,用來表示這個提交作業是新書提交作業。這個 update 函式會將使用者提交的資料儲存至 Cloud Datastore。

    def update(data, id=None):
        ds = get_client()
        if id:
            key = ds.key('Book', int(id))
        else:
            key = ds.key('Book')
    
        entity = datastore.Entity(
            key=key,
            exclude_from_indexes=['description'])
    
        entity.update(data)
        ds.put(entity)
        return from_datastore(entity)
    
    create = update

    get_client 輔助函式會建立和 Cloud Datastore API 互動的用戶端。

    def get_client():
        return datastore.Client(current_app.config['PROJECT_ID'])
    
    

    from_datastore 輔助函式會將 Cloud Datastore 的實體金鑰轉譯為 ID 供應用程式使用。

    def from_datastore(entity):
        """Translates Datastore results into the format expected by the
        application.
    
        Datastore typically returns:
            [Entity{key: (kind, id), prop: val, ...}]
    
        This returns:
            {id: id, prop: val, ...}
        """
        if not entity:
            return None
        if isinstance(entity, builtin_list):
            entity = entity.pop()
    
        entity['id'] = entity.key.id
        return entity

    當使用者新增書籍後,按一下 [Books] (書籍) 連結會前往 /books 頁面,其中會列出 Cloud Datastore 目前儲存的所有書籍。model_datastore.list 函式會使用擷取自 Cloud Datastore 的資料,列出所有書籍。

    def list(limit=10, cursor=None):
        ds = get_client()
    
        query = ds.query(kind='Book', order=['title'])
        query_iterator = query.fetch(limit=limit, start_cursor=cursor)
        page = next(query_iterator.pages)
    
        entities = builtin_list(map(from_datastore, page))
        next_cursor = (
            query_iterator.next_page_token.decode('utf-8')
            if query_iterator.next_page_token else None)
    
        return entities, next_cursor

    這個程式碼會使用 datastore.Query 查詢 Cloud Datastore,取得所有的 Book 實體後,將這些實體傳回,並依 title 排序。您也可以在查詢中套用篩選條件。詳情請參閱 Cloud Datastore 適用的 Python 用戶端

    這個程式碼會使用 query.fetch 反覆運算所有查詢要求。此代碼一次取得一頁結果資料,並傳回游標,以便使用者載入下一頁的結果。

    本頁內容對您是否有任何幫助?請提供意見:

    傳送您對下列選項的寶貴意見...

    這個網頁