Google App Engineで「Hello world!」数パターン
2010/04/20 19:08:08
プレビューリリースから早2年。開発環境も充実してきたようなのでGAE熱が再燃。
まずは「Hello world!」を数パターンで書いてみる。
app.yaml
■パターン1
main.py
■パターン2
main.py
■パターン3
main.py
template/helloworld.html
■パターン4
main.py
helloworld.py
このパターンは「helloworld」を表示するクラス「MainHandler」を別ファイル「helloworld.py」にした形。
たった「helloworld!」を表示するだけのこのボリュームでファイルを分割するなんて大袈裟なのは当然だけど、ちょっと大きなWebアプリを作ろうと思ったら、ファイルを分割=機能のモジュール化は避けて通れない。
といっても小生Python初心者なのでこのやり方が王道なのか、合っているのかは実は今だにわからない。
色々なサンプルソースを見ていると皆そうしているし、なによりテンプレートに分けたとしても処理をいちファイルに全て表記するのはどう考えても良いやり方とは思えない。
■パターン5
main.py
app/__init__.py
app/helloworld.py
パターン4を発展させていくと「main.py」と同階層にモジュールファイルが大量に出来てしまう。
数ファイルならまだしも何百にもなるとちょっと無理があるのでモジュールをフォルダを作って階層で管理しようというわけ。
そう思ってやってみると最初はエラーが出て、このやり方は出来ないのかとまで思ったのだが、任意でフォルダを作った場合はその中に必ず「__init__.py」というファイルが必要だとわかった。
このファイルは同階層のどのファイルを読み込んだとしてもモジュールを読み込んだ時に実行されるのでコンストラクタの役割を果たしていると思われる。
なにも初期処理をする必要がなければ内容は空でよい。
■パターン6
main.py
app/__init__.py
app/helloworld.py
app/helloworld/helloworld.html
app/template/head.html
このやり方はPHPととても似ていますが、デザインによってはいくつもの共通テンプレートを作らなければならなかったりするためあまりスマートな方法とは言えないかもしれません。
■パターン7
main.py
app/helloworld/helloworld.html
app/template.html
この方法はDjangoのテンプレートの継承というのを利用した方法で、block要素を自由に決めて継承元の「template.html」ベーステンプレートに上書きで流し込んでいます。
以上。「Hello world!」の色々な書き方パターンでした。
application: jinling-ren version: 1 runtime: python api_version: 1 handlers: - url: .* script: main.py「app.yaml」は共通。
■パターン1
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html; charset=UTF-8'
self.response.out.write('Hello world!(ハロー・ワールド)')
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
これより下も同様ですが、コードは全て「UTF-8」です。ファイルもそれで保存すること。■パターン2
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld1 = "Hello world!"
str_helloworld2 = "(ハロー・ワールド)"
self.response.out.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>ハロー・ワールド</title>
</head>
<body>
"""+ str_helloworld1 + """%s
</body>
</html>""" % str_helloworld2)
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
■パターン3
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
import os
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld = "Hello world!(ハロー・ワールド)"
output_html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'helloworld.html'),
{
'str_helloworld': str_helloworld
}
)
self.response.out.write(output_html)
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
template/helloworld.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>ハロー・ワールド</title>
</head>
<body>
{{ str_helloworld }}
</body>
</html>テンプレート表示。テンプレートの流れは「テンプレートファイル(htmlとか)」と「ディクショナリ値」をtemplateモジュールに流しこんでレンダリングされたHTMLテキストを返したもらったものを出力するという感じ。■パターン4
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from helloworld import MainHandler
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
helloworld.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
import os
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld = "Hello world!(ハロー・ワールド)"
output_html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'helloworld.html'),
{
'str_helloworld': str_helloworld
}
)
self.response.out.write(output_html)
テンプレートソースはパターン3と同じなので省略。このパターンは「helloworld」を表示するクラス「MainHandler」を別ファイル「helloworld.py」にした形。
たった「helloworld!」を表示するだけのこのボリュームでファイルを分割するなんて大袈裟なのは当然だけど、ちょっと大きなWebアプリを作ろうと思ったら、ファイルを分割=機能のモジュール化は避けて通れない。
といっても小生Python初心者なのでこのやり方が王道なのか、合っているのかは実は今だにわからない。
色々なサンプルソースを見ていると皆そうしているし、なによりテンプレートに分けたとしても処理をいちファイルに全て表記するのはどう考えても良いやり方とは思えない。
■パターン5
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from app.helloworld import MainHandler
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
app/__init__.py
#!/usr/bin/env python #!-*- coding:utf-8 -*-
app/helloworld.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
import os
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld = "Hello world!(ハロー・ワールド)"
output_html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'helloworld.html'),
{
'str_helloworld': str_helloworld
}
)
self.response.out.write(output_html)
これまたテンプレートソースはパターン3と同じなので省略。パターン4を発展させていくと「main.py」と同階層にモジュールファイルが大量に出来てしまう。
数ファイルならまだしも何百にもなるとちょっと無理があるのでモジュールをフォルダを作って階層で管理しようというわけ。
そう思ってやってみると最初はエラーが出て、このやり方は出来ないのかとまで思ったのだが、任意でフォルダを作った場合はその中に必ず「__init__.py」というファイルが必要だとわかった。
このファイルは同階層のどのファイルを読み込んだとしてもモジュールを読み込んだ時に実行されるのでコンストラクタの役割を果たしていると思われる。
なにも初期処理をする必要がなければ内容は空でよい。
■パターン6
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from app.helloworld import MainHandler
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
app/__init__.py
#!/usr/bin/env python #!-*- coding:utf-8 -*-
app/helloworld.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
import os
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld1 = "ハロー・ワールド"
str_helloworld2 = "Hello world!(ハロー・ワールド)"
output_html = template.render(
os.path.join(os.path.dirname(__file__), 'helloworld', 'helloworld.html'),
{
'str_helloworld1': str_helloworld1,
'str_helloworld2': str_helloworld2
}
)
self.response.out.write(output_html)
app/helloworld/helloworld.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
{% include '../template/head.html' %}
</head>
<body>
{{ str_helloworld2 }}
</body>
</html>
app/template/head.html
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>{{ str_helloworld1 }}</title>
テンプレート同士の共通テンプレートという状況はよくある現象です。このパターンは「helloworld.html」テンプレートから別の「head.html」テンプレートを呼び出しています。このやり方はPHPととても似ていますが、デザインによってはいくつもの共通テンプレートを作らなければならなかったりするためあまりスマートな方法とは言えないかもしれません。
■パターン7
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
import os
class MainHandler(webapp.RequestHandler):
def get(self):
str_helloworld1 = "ハロー・ワールド"
str_helloworld2 = "Hello world!(ハロー・ワールド)"
output_html = template.render(
os.path.join(os.path.dirname(__file__), 'helloworld', 'helloworld.html'),
{
'str_helloworld1': str_helloworld1,
'str_helloworld2': str_helloworld2
}
)
self.response.out.write(output_html)
app/helloworld/helloworld.html
{% extends "../template.html" %}
{% block title %}{{ str_helloworld1 }}{% endblock %}
{% block content %}
{{ str_helloworld2 }}
{% endblock %}app/template.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
このパターンはパターン6よりすっきりしていて見る人によっては最良の方法かもしれません。この方法はDjangoのテンプレートの継承というのを利用した方法で、block要素を自由に決めて継承元の「template.html」ベーステンプレートに上書きで流し込んでいます。
以上。「Hello world!」の色々な書き方パターンでした。