第 9 章 アプリケーションのデプロイ 49
15.2 実習 テンプレートを使う
手順2. Jinja2の設定情報の追加
main.pyの先頭に、Jinja2の設定を追加します。jinja2.FileSystemLoader(os.path.dirname(__file__)) で、テンプレートファイルの保存先をmain.pyと同じ場所に指定しています。
1 import jinja2
2
3 JINJA_ENVIRONMENT = jinja2.Environment(
4 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
5 extensions=['jinja2.ext.autoescape'],
6 autoescape=True)
手順3. テンプレートファイルの作成
index.htmlという名前でテンプレートファイルを作成し、次のような内容にします。
テンプレート構文
jinja2では{% ... %}や{{ ... }}などの制御構文が用意されています。{% .. %}はif やforなどの構文が用意され ています。{{ ... }}はpythonコードで定義された変数の内容にアクセスすることができます。
コードの説明
2行目の{% autoescape true %}では、<>などような文字を、htmlで安全に表示できるようにしてい ます。
5行目の{% for todo in todos %}はmain.pyで定義した、todosの内容を繰り返し処理しています。
1 <!DOCTYPE html>
2 {% autoescape true %}
3 <html>
4 <head lang="en">
5 <meta charset="UTF-8">
6 <title></title>
7 </head>
8 <body>
9 <h1>TODOリスト</h1>
10 11 <ul>
12 {% for todo in todos %}
13 <li>{{ todo.content }}</li>
14 {% endfor %}
15
92 第15章 フォームの作成2
16 </ul>
17
18 <form method="post" action="/">
19 <input type="text" name="content">
20 <input type="submit" value="送信" />
21 </form>
22
23 </body>
24 </html>
25 {% endautoescape %}
手順4. レンダリング
MainHandlerからWebページの出力にテンプレートを使うようにするために、次の処理を実装します
• テンプレートファイルで使用するデータを準備する – Dictionaryオブジェクトを生成する
• テンプレートファイルを指定し、レンダリング処理をする
– JINJA_ENVIRONMENT.get_template(’テンプレートファイル’)メソッドを使って、テンプ レートを読み込みます。引数にはテンプレートファイルを指定します。
– template.render(template_values)メソッドを使ってHTML文を生成します。引数に、テ ンプレートファイル側で使用するオブジェクトを指定します。
– 生成されたHTML文を書き出します
1 todos = Todo.query(Todo.author==user.nickname())
2 template_values = {
3 'todos': todos,
4 }
5
6 template = JINJA_ENVIRONMENT.get_template('index.html')
7 self.response.write(template.render(template_values))
手順2. Jinja2の設定情報の追加
main.pyの先頭に、Jinja2の設定を追加します。jinja2.FileSystemLoader(os.path.dirname(__file__)) で、テンプレートファイルの保存先をmain.pyと同じ場所に指定しています。
1 import jinja2
2
3 JINJA_ENVIRONMENT = jinja2.Environment(
4 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
5 extensions=['jinja2.ext.autoescape'],
6 autoescape=True)
手順3. テンプレートファイルの作成
index.htmlという名前でテンプレートファイルを作成し、次のような内容にします。
テンプレート構文
jinja2では{% ... %}や{{ ... }}などの制御構文が用意されています。{% .. %}はif やforなどの構文が用意され ています。{{ ... }}はpythonコードで定義された変数の内容にアクセスすることができます。
コードの説明
2行目の{% autoescape true %}では、<>などような文字を、htmlで安全に表示できるようにしてい ます。
5行目の{% for todo in todos %}はmain.pyで定義した、todosの内容を繰り返し処理しています。
1 <!DOCTYPE html>
2 {% autoescape true %}
3 <html>
4 <head lang="en">
5 <meta charset="UTF-8">
6 <title></title>
7 </head>
8 <body>
9 <h1>TODOリスト</h1>
10 11 <ul>
12 {% for todo in todos %}
13 <li>{{ todo.content }}</li>
14 {% endfor %}
15
92 第15章 フォームの作成2
16 </ul>
17
18 <form method="post" action="/">
19 <input type="text" name="content">
20 <input type="submit" value="送信" />
21 </form>
22
23 </body>
24 </html>
25 {% endautoescape %}
手順4. レンダリング
MainHandlerからWebページの出力にテンプレートを使うようにするために、次の処理を実装します
• テンプレートファイルで使用するデータを準備する – Dictionaryオブジェクトを生成する
• テンプレートファイルを指定し、レンダリング処理をする
– JINJA_ENVIRONMENT.get_template(’テンプレートファイル’)メソッドを使って、テンプ レートを読み込みます。引数にはテンプレートファイルを指定します。
– template.render(template_values)メソッドを使ってHTML文を生成します。引数に、テ ンプレートファイル側で使用するオブジェクトを指定します。
– 生成されたHTML文を書き出します
1 todos = Todo.query(Todo.author==user.nickname())
2 template_values = {
3 'todos': todos,
4 }
5
6 template = JINJA_ENVIRONMENT.get_template('index.html')
7 self.response.write(template.render(template_values))
15.2 実習 テンプレートを使う
メインページをテンプレートを使って表示させましょう。
15.2. 実習 テンプレートを使う 93
15.2.1 実習の手順
1. ライブラリの追加
2. テンプレートファイルの作成 3. main.pyの修正
手順1. ライブラリの追加
app.yamlに次の内容を追加します。
1 libraries:
2 - name: webapp2
3 version: latest
4 - name: jinja2
5 version: latest
手順2. テンプレートファイルの作成
テンプレートファイルindex.htmlを作成します。
1 <!DOCTYPE html>
2 {% autoescape true %}
3 <html>
4 <head lang="en">
5 <meta charset="UTF-8">
6 <title></title>
7 </head>
8 <body>
9 <h1>TODOリスト</h1>
10 11 <ul>
12 {% for todo in todos %}
13 <li>{{ todo.content }}</li>
14 {% endfor %}
15
16 </ul>
17
18 <form method="post" action="/">
19 <input type="text" name="content">
20 <input type="submit" value="送信" />
21 </form>
22
23 </body>
94 第15章 フォームの作成2
24 </html>
25 {% endautoescape %}
手順3. MainHandlerの修正
MainHandlerに次の処理を追加します
• Jinja2の設定情報の追加
1 import jinja2
2
3 JINJA_ENVIRONMENT = jinja2.Environment(
4 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
5 extensions=['jinja2.ext.autoescape'],
6 autoescape=True)
• getメソッドにテンプレートファイルの読み込みとレンダリング処理の追加
1 class MainHandler(webapp2.RequestHandler):
2 def get(self):
3 user = users.get_current_user()
4 if user is None:
5 self.redirect(users.create_login_url(self.request.uri))
6 return
7 todos = Todo.query(Todo.author==user.nickname())
8 template_values = {
9 'todos': todos,
10 }
11
12 template = JINJA_ENVIRONMENT.get_template('index.html')
13 self.response.write(template.render(template_values))
main.py
main.pyは次のような内容になります。
1 # coding: utf-8
-*-2 #!/usr/bin/env python
3 #
4 # Copyright 2007 Google Inc.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
15.2. 実習 テンプレートを使う 95
15.2.1 実習の手順
1. ライブラリの追加
2. テンプレートファイルの作成 3. main.pyの修正
手順1. ライブラリの追加
app.yamlに次の内容を追加します。
1 libraries:
2 - name: webapp2
3 version: latest
4 - name: jinja2
5 version: latest
手順2. テンプレートファイルの作成
テンプレートファイルindex.htmlを作成します。
1 <!DOCTYPE html>
2 {% autoescape true %}
3 <html>
4 <head lang="en">
5 <meta charset="UTF-8">
6 <title></title>
7 </head>
8 <body>
9 <h1>TODOリスト</h1>
10 11 <ul>
12 {% for todo in todos %}
13 <li>{{ todo.content }}</li>
14 {% endfor %}
15
16 </ul>
17
18 <form method="post" action="/">
19 <input type="text" name="content">
20 <input type="submit" value="送信" />
21 </form>
22
23 </body>
94 第15章 フォームの作成2
24 </html>
25 {% endautoescape %}
手順3. MainHandlerの修正
MainHandlerに次の処理を追加します
• Jinja2の設定情報の追加
1 import jinja2
2
3 JINJA_ENVIRONMENT = jinja2.Environment(
4 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
5 extensions=['jinja2.ext.autoescape'],
6 autoescape=True)
• getメソッドにテンプレートファイルの読み込みとレンダリング処理の追加
1 class MainHandler(webapp2.RequestHandler):
2 def get(self):
3 user = users.get_current_user()
4 if user is None:
5 self.redirect(users.create_login_url(self.request.uri))
6 return
7 todos = Todo.query(Todo.author==user.nickname())
8 template_values = {
9 'todos': todos,
10 }
11
12 template = JINJA_ENVIRONMENT.get_template('index.html')
13 self.response.write(template.render(template_values))
main.py
main.pyは次のような内容になります。
1 # coding: utf-8
-*-2 #!/usr/bin/env python
3 #
4 # Copyright 2007 Google Inc.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
15.2. 実習 テンプレートを使う 95
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 from google.appengine.api import users
19 from google.appengine.ext import ndb
20 import cgi
21 import os
22 import jinja2
23 import webapp2
24 import logging
25
26 JINJA_ENVIRONMENT = jinja2.Environment(
27 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
28 extensions=['jinja2.ext.autoescape'],
29 autoescape=True)
30 31
32 class Todo(ndb.Model):
33 """Models an individual Todo entry with author, content, and date."""
34 author = ndb.StringProperty()
35 content = ndb.StringProperty(indexed=False)
36 date = ndb.DateTimeProperty(auto_now_add=True)
37 38
39 class MainHandler(webapp2.RequestHandler):
40 def get(self):
41 user = users.get_current_user()
42 if user is None:
43 self.redirect(users.create_login_url(self.request.uri))
44 return
45 todos = Todo.query(Todo.author==user.nickname())
46 template_values = {
47 'todos': todos,
48 }
49
50 template = JINJA_ENVIRONMENT.get_template('index.html')
51 self.response.write(template.render(template_values))
52 53
54 def post(self):
55 # content = cgi.escape(self.request.get('content'))
56 # self.response.write('New Todo:' + content)
96 第15章 フォームの作成2
57 user = users.get_current_user()
58 if user is None:
59 self.redirect(users.create_login_url(self.request.uri))
60 return
61
62 todo = Todo()
63 todo.content = cgi.escape(self.request.get('content'))
64 todo.author = user.nickname()
65 key = todo.put()
66 logging.info("key=%s" % str(key))
67 self.redirect('/')
68 69
70 class MyPageHandler(webapp2.RequestHandler):
71 def get(self):
72 user = users.get_current_user()
73 if user:
74 self.response.headers['Content-Type'] = 'text/plain'
75 self.response.write('Hello, ' + user.nickname())
76 else:
77 self.redirect(users.create_login_url(self.request.uri))
78 return
79 80
81 def handle_404(request, response, exception):
82 logging.exception(exception)
83 response.write('ページが見つかりませんでした。')
84 response.set_status(404)
85 86
87 app = webapp2.WSGIApplication([
88 ('/', MainHandler),
89 ('/mypage', MyPageHandler)
90 ], debug=True)
91
92 app.error_handlers[404] = handle_404
15.2.2 確認
メインページにアクセスし、一覧が表示されていることを確認します。
15.2.3 解答
解答ドキュメントを参照してください。
15.2. 実習 テンプレートを使う 97
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 from google.appengine.api import users
19 from google.appengine.ext import ndb
20 import cgi
21 import os
22 import jinja2
23 import webapp2
24 import logging
25
26 JINJA_ENVIRONMENT = jinja2.Environment(
27 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
28 extensions=['jinja2.ext.autoescape'],
29 autoescape=True)
30 31
32 class Todo(ndb.Model):
33 """Models an individual Todo entry with author, content, and date."""
34 author = ndb.StringProperty()
35 content = ndb.StringProperty(indexed=False)
36 date = ndb.DateTimeProperty(auto_now_add=True)
37 38
39 class MainHandler(webapp2.RequestHandler):
40 def get(self):
41 user = users.get_current_user()
42 if user is None:
43 self.redirect(users.create_login_url(self.request.uri))
44 return
45 todos = Todo.query(Todo.author==user.nickname())
46 template_values = {
47 'todos': todos,
48 }
49
50 template = JINJA_ENVIRONMENT.get_template('index.html')
51 self.response.write(template.render(template_values))
52 53
54 def post(self):
55 # content = cgi.escape(self.request.get('content'))
56 # self.response.write('New Todo:' + content)
96 第15章 フォームの作成2
57 user = users.get_current_user()
58 if user is None:
59 self.redirect(users.create_login_url(self.request.uri))
60 return
61
62 todo = Todo()
63 todo.content = cgi.escape(self.request.get('content'))
64 todo.author = user.nickname()
65 key = todo.put()
66 logging.info("key=%s" % str(key))
67 self.redirect('/')
68 69
70 class MyPageHandler(webapp2.RequestHandler):
71 def get(self):
72 user = users.get_current_user()
73 if user:
74 self.response.headers['Content-Type'] = 'text/plain'
75 self.response.write('Hello, ' + user.nickname())
76 else:
77 self.redirect(users.create_login_url(self.request.uri))
78 return
79 80
81 def handle_404(request, response, exception):
82 logging.exception(exception)
83 response.write('ページが見つかりませんでした。')
84 response.set_status(404)
85 86
87 app = webapp2.WSGIApplication([
88 ('/', MainHandler),
89 ('/mypage', MyPageHandler)
90 ], debug=True)
91
92 app.error_handlers[404] = handle_404
15.2.2 確認
メインページにアクセスし、一覧が表示されていることを確認します。
15.2.3 解答
解答ドキュメントを参照してください。
15.2. 実習 テンプレートを使う 97
第 16 章
スタティックファイルを使う
16.1 スタティックファイルの利用
最近のWebページはcssやjavascriptなどのリソースを読み込み、見栄えのいい使いやすいUIを実現していま す。通常、cssやjavascriptは外部ファイルとして提供されており、Webページは画面表示のタイミングでそれら のファイルを読み込みます。また、外部リソースは動的に変化するものではなく、静的で常に同じものを扱いま す。この章ではGAEで、静的なファイルの扱い方について説明します。
16.1.1 スタティックファイルの使い方
ここでは、CSSフレームワークのBootstarpをスタティックファイルとして用意し、それをindex.htmlで読みま す。手順は概ね次のようになります。
手順
1. スタティックファイルの追加
2. スタティックファイルハンドラの追加 3. スタティックファイルの読み込み
手順1. スタティックファイルの追加
Bootstrapの公式サイトより(http://getbootstrap.com/) 最新版を取得します。zipファイルを解凍すると、css、js、 fontsフォルダが作成されます。次にstaticフォルダを作成し、css、js、fontsフォルダを配置します。
helloworld
└-- static # 新規作成
├-- css # bootstrap
第 16 章
スタティックファイルを使う
16.1 スタティックファイルの利用
最近のWebページはcssやjavascriptなどのリソースを読み込み、見栄えのいい使いやすいUIを実現していま す。通常、cssやjavascriptは外部ファイルとして提供されており、Webページは画面表示のタイミングでそれら のファイルを読み込みます。また、外部リソースは動的に変化するものではなく、静的で常に同じものを扱いま す。この章ではGAEで、静的なファイルの扱い方について説明します。
16.1.1 スタティックファイルの使い方
ここでは、CSSフレームワークのBootstarpをスタティックファイルとして用意し、それをindex.htmlで読みま す。手順は概ね次のようになります。
手順
1. スタティックファイルの追加
2. スタティックファイルハンドラの追加 3. スタティックファイルの読み込み
手順1. スタティックファイルの追加
Bootstrapの公式サイトより(http://getbootstrap.com/) 最新版を取得します。zipファイルを解凍すると、css、js、 fontsフォルダが作成されます。次にstaticフォルダを作成し、css、js、fontsフォルダを配置します。
helloworld
└-- static # 新規作成
├-- css # bootstrap