• 検索結果がありません。

第 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

9215章 フォームの作成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

9215章 フォームの作成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>

9415章 フォームの作成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>

9415章 フォームの作成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)

9615章 フォームの作成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)

9615章 フォームの作成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