シンプルなゲストブックの作成

プロジェクトを作成する

前のセクションにて説明してある通り、gaeo.py スクリプトを gbook アプリケーションを作るために使います

# gaeo gbook

メッセージフォーム

最初に、訪問者がメッセージを残せるように、フォームを作成します。ルートページ (url '/') がデフォルトではwelcome コントローラの index アクションにディスパッチされます。つまり、ルートページに対しての処理は、welcome コントローラに対してコードを記述すれば良いことになります。

welcome コントーラは WelcomeController クラスであり application/controller/welcome.py にファイルがあります。最初は、welcome.py の内容は以下のようになっているでしょう:

from gaeo.controller import BaseController

class WelcomeController(BaseController):
    def index(self):
        pass

WelcomeController クラスには index メソッドがあります。 index メソッドは index アクション のハンドラを意味しています。 とりあえずブランク(つまりコード「pass」) のままにしておきましょう。

URL '/' がwelcome コントローラの index メソッドにディスパッチされるので、 デフォルトの出力は application/templates/welcome/index.html テンプレートになります。 このファイルに下記のようにフォームを追加してみましょう。:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>GAEO Book</title>
    </head>
    <body>
      <form method="post" action="/speak">
        <fieldset>
            <legend>Leave a message</legend>
            <p>
                <label>Name:</label><br>
                <input type="text" name="username" size="20">
            </p>
            <p>
                <label>Message:</label><br>
                <textarea name="message" rows="5" cols="40"></textarea>
            </p>
            <p>
                <input type="submit" value="Post">
            </p>
        </fieldset>
      </form>
    </body>
</html>

このように、2つのフィールドを持つフォームを作成しました。1つは訪問者の名前、もう1つはメッセージを入力するフィールドです。訪問者が"Post"ボタンを押した場合、フォームはHTTP POSTリクエストを URL '/speak' へ送信します。次にこのリクエストを処理してみましょう。

ルーティングルールを追加する

GAEO はデフォルトのルーティングルールを持っていますが、(例えば, '/'{'controller': 'welcome', 'action': 'index'}へディスパッチされます), URL '/speak' にはルールがありません。カスタムルールを作成するのは簡単です。main.py ファイルを開き、initRoutes メソッドを見つけてください:

def initRoutes():
    r = router.Router()

    #TODO: add routes here

    r.connect('/:controller/:action/:id')

gaeo.py スクリプトによって上記コードが生成されています。URL '/speak' に対するルールを下記のように加えてみましょう

def initRoutes():
    r = router.Router()
    r.connect('/speak', controller='welcome', action='speak')
    r.connect('/:controller/:action/:id')

コードを追加した後、URL '/speak'  はwelcome コントローラの speak アクションにディスパッチされます。 speak メソッドをWelcomeController クラスに追加して、 '/speak' リクエストを処理しましょう。

データを保存する

speak メソッドを実装する前に、データモデルを最初に定義しましょう。アプリケーションのルート (たとえば., /home/ericsk/Demos/gbook) で、gaeogen.py スクリプトを下記のようにしてデータモデルクラスを生成するために実行します:

gaeogen model Message

最初の引数は生成する対象のタイプ、第二引数はデータモデル名です。上記のコマンドにより Message クラスが application/models/message.py に生成されます。内容は下記のようになるでしょう。

from google.appengine.ext import db
from gaeo.model import BaseModel

class Message(BaseModel):
    pass

モデルを生成した後、どのようなデータをこのモデルに保存するかを指定します。下記のようにコードを追加します:

from google.appengine.ext import db
from gaeo.model import BaseModel

class Message(BaseModel):
    username = db.StringProperty(required=True)
    content = db.TextProperty(required=True)
    post_at = db.DateTimeProperty(auto_now_add=True)

3つのフィールドをこのモデルでは保存します:
  • username 訪問者名
  • content メッセージ
  • post_at メッセージが送信された時刻
これらのコードは フィールドのタイプを定義するためにデータストアAPI を利用しています。これらのタイプの意味や、どんな種類があるかを知りたい場合にはApp Engineのドキュメントを読んでください。

処理を行い、データを実際に保存する

speak アクションに戻ります。 URL '/speak'{'controller':'welcome', 'action':'speak'} にディスパッチするカスタムルールを作成したので, we have WelcomeController にspeakメソッドを追加します:

# application/controllers/welcome.py
from gaeo.controller import BaseController

# import the model class
from model.message import Message

class WelcomeController(BaseController):
    def index(self):
        pass
        
    def speak(self):
        try:
            # modelのインスタンスを作成し、リクエストパラメータからデータを受け取る
            msg = Message(
                    username=self.params['username'],
                    content=self.params['message']
                    )
            # データの保存
            msg.put()
            # URL '/' にリダイレクト
            self.redirect('/')
        except Exception, ex:
            # 例外メッセージを表示する
            self.render(text='Exception: %s' % ex)

データを App Engine の bigtable に保存するのは簡単です。-- モデルのインスタンスを作成し、put メソッドを呼び出します。リクエストデータ (メッセージフォームから送信されたもの) は self.params オブジェクト (ディクショナリ) に保存され、キーはフォームのフィールド名にマップされます。データが保存されると、 '/' にリダイレクトされます。

もしエラーが発生した場合には except ブロックで例外メッセージをself.render メソッドにより出力します。

保存されたデータの確認

メッセージを表示する前にデータが bigtable に保存されたかを確認しましょう。 http://localhost:8080/_ah/admin/datastore のURL にて開発用マシンのストレージの状態を確認できます。  Entity Kind は field, type が Message で、Messageモデルのデータを確認できます。

Macの Launcherを使っている場合、このページへはSDK Console タブからアクセスできます。

保存されたメッセージを表示する

もしメッセージが正しく保存されていれば、それらをページ上で表示できます。root ページで表示したい場合は index アクションでデータを取得する必要があります。:

# application/controllers/welcome.py
...

def index(self):
    # すべでのメッセージを取得
    self.msgs = Message.all()
    # post_atで降順で50件取得
    self.msgs.order('-post_at')
    self.msgs.fetch(50)

...

コントローラにインスタンス変数を追加してテンプレートでその変数を利用できるようにします。index テンプレートを開いてメッセージを表示させます。

<!-- application/templates/welcome/index.html -->
...
...
<div id="messages">
  {% if msgs %}
  <ul>
    {% for msg in msgs %}
    <li>
      <h3>{{ msg.username }}:</h3>
      <p>{{ msg.content }}</p>
      <hr>
      <p style="text-align:right;"><small>At {{ msg.post_at|date }}</small></p>
    </li>
    {% endfor %}
  </ul>
  {% else %}
  <h1>メッセージはありません</h1>
  {% endif %}
</div>
...
...

これでシンプルなゲストブックアプリケーションができました。
Comments