Google App Engine:データストアに保存したテンプレートを使う。

Google App Engine のテンプレート・モジュールは、google.appengine.ext.webapp パッケージからインポートし、rendar() メソッドで、テンプレート・ファイルのパスとテンプレート・データを指定して実行するものです。

これはこれで、非常に簡潔で便利なものですが、テンプレート・ファイルを静的ファイルとしてアップロードしなければなりません。ちょっと直したいときには、少し不便です。もし、テンプレートの編集がブラウザ上で可能ならば、便利かと思います。

前回の「Google App Engine:django.template を使う。」で紹介した方法を用いれば、テンプレート・ファイルのパスを指定するのではなく、テンプレート文字列に直接、テンプレート・データを埋め込むことができます。

テンプレート文字列を取得する先として、データストアを利用すれば、ブラウザ上で編集が可能です。

このような考えで、データストアに保存したテンプレートを使って見たところうまくいきました。

テンプレートのためのデータストア用のクラス

まず、テンプレートのためのデータストア用のクラスを用意しましょう。

# MyTemplate.py
from google.appengine.ext import db

class MyTemplate(db.Model):
  title = db.StringProperty()
  content = db.TextProperty()

項目としては、最低限、タイトルと内容があれば十分です。
タイトル(title)には、「example.tpl」など、テンプレートを識別するための文字列を入れ、内容(content)には、テンプレートを入れます。

入力用フォーム

次に、これに入力するためのフォームを作成します。

<!-- MyTemplateForm.html -->
<form action="/myTemplateCreate" method="post">
  <input name="title"  type='text' size="60" value='example.tpl' />
  <textarea name="content" rows="3" cols="60"></textarea>
  <input type="submit" value="Submit">
</form>

テキストボックスには、django の記述方法に従ったテンプレートの内容を入力します。

テンプレート例

{% for entry in entries %}
<div>entry: {{ entry.val }}</div>
{% endfor %}

入力処理

このフォームに入力して送信します。
そうすると、「/myTemplateCreate」にリクエストが POST メソッドで送られます。
app.yaml でリクエストハンドラを次のように設定しておけば、「myTemplateCreate.py」にマッピングされます。

- url: /myTemplateCreate
  script: myTemplateCreate.py

「myTemplateCreate.py」の内容は、次のようなものでよいでしょう。

# MyTemplateCreate.py

import cgi
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

from myTemplate import MyTemplate

class MyTemplateCreate(webapp.RequestHandler):
  def post(self):
    myTemplate = MyTemplate()
    myTemplate.title   = self.request.get('title')
    myTemplate.content = self.request.get('content')
    myTemplate.put()
    self.redirect('/') #適当な先にリダイレクト

application = webapp.WSGIApplication([
               ('/myTemplateCreate', MyTemplateCreate),
              ], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

これで、入力したテンプレートが、データストアに保存されます。
後は、このテンプレートを呼び出して、テンプレート・データを埋め込むためのスクリプトを作成して、表示させます。

表示用スクリプト

そのスクリプト・ファイルを「showEntires.py」とでもしておきましょう。
「app.yaml」のリクエスト・ハンドラに次の記述を追加します。

- url: /showEntries
  script: showEntries.py

「showEntries.py」の内容は次のようなものになります。

# showEntries.py

import cgi
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

import django.conf
try:
  django.conf.settings.configure(
    DEBUG=False,
    TEMPLATE_DEBUG=False,
  )
except (EnvironmentError, RuntimeError):
  pass
import django.template

from myTemplate import MyTemplate
from entry import Entry

class ShowEntries(webapp.RequestHandler):
  def get(self):
    template_all = MyTemplate.all()
    title="example.tpl"
    tpl = template_all.filter("title =",title).get().content
    t = django.template.Template(tpl)
    
    entries_all = Entry.all()
    entries_q = entries_all.order('-date')
    entries = entries_q.fetch(10)
    c = django.template.Context( {'entries':entries})
    self.response.out.write(t.render(c))

application = webapp.WSGIApplication([
               ('/showEntries', ShowEntries),
              ], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

テンプレート・データ

なお、ここにある「Entry」は、データストアに保存されている記事を指します。サンプルコードを実行する際には、データを保存しておき、テンプレートとのマッピングを行って下さい。

# entry.py
from google.appengine.ext import db

class MyTemplate(db.Model):
  val = db.StringProperty()
  date = db.DateTimeProperty(auto_now_add=True)