2011年05月23日

GAE+Pythonでテンプレートエンジンを使ったデザインの外部化と静的ファイルの扱い方。

前回はデータストアの操作を説明した。
今回はテンプレートを使用してHTMLやCSSなどのデザイン部分を外部化する方法と静的ファイルの扱い方を説明する。

GAE for Python は有名所のPython用テンプレートシステム(例えば、EZT、Cheetah、ClearSilver、Quixote、Django 等)が、ほぼどれでも使える。とは言え、webapp フレームワークにはデフォルトで Django のテンプレートエンジンが用意されているのでそれを使うのが手っ取り早い。

というわけで、早速その使い方を説明する。


■HTMLを外部化

まずは、いつもの helloworld.py を以下のソースコードに書き換えて見てよう。
# -*- coding: utf-8 -*-
import cgi
import os

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.webapp import template
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):
greetings_query = Greeting.all().order('-date')
greetings = greetings_query.fetch(10)

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))

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 フォルダに新規で index.html というファイルを作り、以下のようにDjangoテンプレートの作法に則って編集する。詳細についてはDjango組み込みタグ・フィルタリファレンスをチェックすべし。
<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>


さて、ここまでできたら開発用サーバを起動し、 http://localhost:8080 へアクセスしてみよう。

アプリ画面の一番下に Login というリンクが作られた筈だ。
このリンクをクリックするとダミーのログイン画面が出現するので、そこで適当なメールアドレスを入力するとダミーログイン状態になる。そして、メイン画面でメッセージを投稿するたびに自分のメアドも登録&表示されるようになる。


では上のソースコードから重要な箇所を抜き出して説明してみよう。

まず、テンプレートエンジンを利用するために以下のように関連モジュールを読み込んでいる。
import os
from google.appengine.ext.webapp import template


そして以下のようにしてテンプレートエンジンを扱う。
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))

直感的に分かる人もいるだろうが一応説明しておくと、template_values = {...} という箇所でテンプレート(index.html)で使用されているキー( {{ hoge }} のように記述されている部分)とそこへ格納する値を紐付けており、path = os.path.join(os.path.dirname(__file__), 'index.html')で index.html の絶対パスを取得し、最後に template.render(path, template_values) で index.html へテンプレートを適用&レンダリングされたHTMLテキストを返している。

なお、テンプレートを共通化してメンテナンス性を更に高めたい場合はこちらを参照のこと。


■CSSや画像も外部化

次は、スタイルシートや画像などの静的ファイルを扱えるようにしてみよう。
まず、app.yamlを以下のように書き換える。
application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /stylesheets
static_dir: stylesheets

- url: /.*
script: helloworld.py

そして、helloworld/stylesheets フォルダを作成して、そこへ main.css というファイルを作成し、以下のように書く。
body {
font-family: Verdana, Helvetica, sans-serif;
background-color: #DDDDDD;
}


次に先程の index.html にこのスタイルシートを読み込ませるために<html>直下に以下のような記述を追加する。
  <head>
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
</head>


これでページをリロードしてみればスタイルシートが適用されている筈だ。

app.yaml に追加された、
- url: /stylesheets
static_dir: stylesheets

という部分は、/stylesheetsというURLへのアクセスがstylesheetsというフォルダ配下にある静的ファイルへのアクセスであることを表している。

画像の静的ファイルを使いたい場合も上と同様に、app.yamlhandlers:の下へ
- url: /images
static_dir: images

を追加し、helloworld/imagesフォルダを作り、そこへ適当な画像ファイル(例えば hoge.jpg)を保管すれば、index.html内で以下のようにして画像が扱えるようになる。
<img src="/images/hoge.jpg" />


要するにCSSだろうが画像だろうが、静的ファイルを扱いたい場合は app.yaml を弄って明示的にファイルの場所を指定すればいいということだ。


GAE for Pythonにおけるデザインの外部ファイル化は以上である。

次回はGAEアプリのアップロードを説明する。いよいよあなたのアプリが世界へお披露目されるというわけだ。


(続く)



posted by 寄り道退屈男 at 17:48 | Comment(0) | TrackBack(0) | GAE for Python
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/45435061
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック