テンプレートで保守性UP!

Using Templates

テンプレートを使って、コードが煩雑になるのを防ぐ。
テンプレートを使うにあたり以下のモジュールをそれぞれimportします。

import os
from google.appengine.ext.webapp import template

その後、MainPageでの処理を以下のように変更

class MainPage(webapp.RequestHandler):
 def get(self):
  greetings = Greeting.all().order('-date')

  if users.get_current_user():
   url = users.create_logout_url(self.request.uri)
   url_linktext = 'Logout'
  else:
   url = users.create_login_url(self.request.uri)
   url_linktext = 'Login'

  template_values = {
   'greetings': greetings,
   'url': url,
   'url_linktext': url_linktext,
   }

  path = os.path.join(os.path.dirname(__file__), 'index.html')
  self.response.out.write(template.render(path, template_values))

最後にhelloworld.pyと同じ位置に以下のHTMLファイルをindex.htmlという名前で作成します。

<html>
 <body>
  {% for greeting in greetings %}
   {% if greeting.author %}
    <b>{{ greeting.author.nickname }}</b> wrote:
   {% else %}
    An anonymous person wrote:
   {% endif %}
   <blockquote>{{ greeting.content|escape }}</blockquote>
  {% endfor %}

  <form action="/sign" method="post">
   <div><textarea name="content" rows="3" cols="60"></textarea></div>
   <div><input type="submit" value="Sign Guestbook"></div>
  </form>

  <a href="{{ url }}">{{ url_linktext }}</a>

 </body>
</html>

あとはリロードするだけで、前回までと同じ動作をします。

1つずつコードを紐解いてみる
  • helloworld.py

path = os.path.join(os.path.dirname(__file__), 'index.html')

helloworld.pyと同じディレクトリにあるindex.htmlへのフルパスを取得している。

self.response.out.write(template.render(path, template_values))

templateモジュールのrender関数を使って、テンプレートファイルとそのファイルに渡す値(template_values)を処理している。
渡す値には、greetings,url,url_linktextの3つが含まれる。

template_values = {
   'greetings': greetings,
   'url': url,
   'url_linktext': url_linktext,
   }

Pythonでの変数の初期化はこんな感じでできるのか。JSONの書き方に近い?

  • index.html

見慣れたHTMLタグの所々に{}で囲まれたものがある。

{% for greeting in greetings %}
{% if greeting.author %}
{% else %}
{% endif %}
{% endfor %}

{% 〜 %}で囲まれているフィールドはどうやら構文を表すみたい。
for、ifなどおなじみの構文なので特に難しくはない。あとは構文の記法に慣れるだけ。

そしてもう1種類。

{{ greeting.author.nickname }}
{{ greeting.content|escape }}
{{ url }}
{{ url_linktext }}

{{ 〜 }}で囲まれているフィールドは呼び出し側からのデータ(今回はtemplate_valuesにあたるデータ)を扱うために使用されている。

テンプレートを使ってみて

前回は受け取ったデータ全てをMainPageで出力していた。

self.response.out.write('%s wrote:' % greeting.author.nickname())

今回は、出力するデータをテンプレート用HTMLファイルに投げて出力している。
「データは渡すからあとはお願いね」というわけで、ロジックとビューが切り離された。

データを

  • 処理する helloworld.py
  • 表示する index.html

煩雑だった箇所が無くなり保守性が上がった事と、index.htmlにあたるファイルを変更することで、見た目だけにタッチする事ができるようになった。
肥大化するアプリケーションで一番の問題となる保守性の悪化を抑えるために覚えておきたいテクニックだと思った。