HOME > ブログ > ブログをGoogle App Engineへ移行してみる16

ブログをGoogle App Engineへ移行してみる16

3歩進んで2歩戻るみたい。以前作ったテンプレート表示render()周りが気に入らなくなってきた。






継承とかを調べていたら以下の記事に出くわしたので。

Google App Engine/Python でリクエストハンドラーの共通処理を簡潔にまとめる方法(2010/07/06)
Google App Engine/Pythonでユーザ認証の共通処理をする方法(2011/01/14)

色々見ている内に現在の構成、作り方が気に入らなくなってきたので、まずはテンプレート周りから変更する。

変更した上でもまだ迷っているが、単一継承にするのか多重継承にするのか、どちらがいいのかはまだわからない。後々ダメだとわかったら変更を承知の上で「多重継承」を採用して下記のようにしてみた。

ファイル・フォルダ構成
│  admin.py
│  app.yaml
│  main.py
│  model.py
│  utils.py
│
├─static
│  │  all.css
│  │  style.css
│  │
│  └─admin
│          style.css
│
├─template
│      base.html
│      EntryList.html
│      EntryList.html
│ 
└─template_admin
        base.html
        CategoryEdit.html
        CategoryList.html
        CategoryNew.html
        EntryEdit.html
        EntryList.html
        EntryNew.html
「layout.html」は「base.html」という名称に変更してみた。特に理由はない。それぞれのテンプレートファイルをフォルダ階層を解除してこのテンプレートファイルが対応するリクエストハンドラーと同じ名称にした。

/admin.py
#!-*- coding:utf-8 -*-
import logging
import os
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from model import Entry, Category
from utils import View



##### This view below is "Entry" #################

class EntryList(webapp.RequestHandler, View):
    def get(self):
        self.template_values['entries'] = Entry.get_entries()
        self.render()

class EntryNew(webapp.RequestHandler, View):
    def get(self):
        self.template_values['categories'] = Category.get_categories()
        self.render()

    def post(self):
        entry = Entry()
        entry.title = self.request.get("title")
        entry.body = self.request.get("body")
        entry.categories = self.request.get_all("categories")
        entry.put()
        self.redirect("/admin/")

class EntryEdit(webapp.RequestHandler, View):
    def get(self, key):
        self.template_values['entry'] = Entry.get_entry(key, True)
        self.render()

    def post(self, key):
        entry = db.get(db.Key(key))
        entry.title = self.request.get("title")
        entry.body = self.request.get("body")
        entry.categories = self.request.get_all("categories")
        entry.put()
        self.redirect("/admin/")

class EntryDelete(webapp.RequestHandler):
    def get(self, key):
        entry = db.get(db.Key(key))
        if entry:
            entry.delete()
        self.redirect("/admin/")



##### This view below is "Category" #################

class CategoryList(webapp.RequestHandler, View):
    def get(self):
        self.template_values['categories'] = Category.get_categories()
        self.render()

class CategoryNew(webapp.RequestHandler, View):
    def get(self):
        self.render()

    def post(self):
        category = Category()
        category.name = self.request.get("name")
        category.put()
        self.redirect("/admin/category/")

class CategoryEdit(webapp.RequestHandler, View):
    def get(self, key):
        self.template_values['category'] = Category.get_category(key)
        self.render()

    def post(self, key):
        category = db.get(db.Key(key))
        category.name = self.request.get("name")
        category.put()
        self.redirect("/admin/category/")

class CategoryDelete(webapp.RequestHandler):
    def get(self, key):
        category = db.get(db.Key(key))
        if category:
            category.delete()
        self.redirect("/admin/category/")


/main.py
#!-*- coding:utf-8 -*-
import logging
import os
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from model import Entry, Comment
import admin
from utils import View



class EntryList(webapp.RequestHandler, View):
    def get(self):
        self.template_values['entries'] = Entry.get_entries()
        self.render()

class EntryShow(webapp.RequestHandler,View):
    def get(self, key):
        self.template_values['entry'] = Entry.get_entry(key)
        self.render()

class CommentNew(webapp.RequestHandler):
    def post(self, key):
        entry = db.get(db.Key(key))
        if entry:
            comment = Comment(parent=entry)
            comment.comment = self.request.get("comment")
            comment.put()
            self.redirect("/entry/show/"+key)
        else:
            self.redirect("/")

application = webapp.WSGIApplication([
                                     ('/', EntryList),
                                     ('/entry/show/([\w\-]+)', EntryShow),
                                     ('/comment/new/([\w\-]+)', CommentNew),
                                     ('/admin/', admin.EntryList),
                                     ('/admin/new', admin.EntryNew),
                                     ('/admin/edit/([\w\-]+)', admin.EntryEdit),
                                     ('/admin/delete/([\w\-]+)', admin.EntryDelete),
                                     ('/admin/category/', admin.CategoryList),
                                     ('/admin/category/new', admin.CategoryNew),
                                     ('/admin/category/edit/([\w\-]+)', admin.CategoryEdit),
                                     ('/admin/category/delete/([\w\-]+)', admin.CategoryDelete)
                                     ],debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()


/utils.py
class View(object):
    template_values = {}
    def __init__(self):
        pass

    def render(self):
        template_dir = 'template_admin' if (self.__module__ == 'admin') else 'template'
        template_name = self.__class__.__name__ + '.html'
        path = os.path.join(os.path.dirname(__file__), template_dir, template_name)
        self.response.out.write(template.render(path, self.template_values))
このクラスを追記する。


テンプレートでレンダリングするリクエストハンドラーには「utils.py」に追記した「View」クラスを多重継承してやる。「View」クラスにて「template_values」というディクショナリは定義されているので、テンプレートに渡す値を追加したい場合は辞書に追加してやればよい。
self.template_values['entries'] = Entry.get_entries()
こんな感じで。これは
self.template_values.update({'entries': Entry.get_entries()})
としても同じ。
で最後にレンダリングするのは「self.render()」とするだけ。

少し困ったのは管理と表示ではテンプレートフォルダが違う点。引数として渡せばいけそうだが、それではカッコが悪いしスッキリしない。別のフォルダにするのではなく同じフォルダにしようかとも考えたが(最終的にはそうした方がひょっとしたらいいかも)、リクエストハンドラー名を一意に変更する必要が出てくるので面倒くさい。

で、現状落ち着いたのが、「View」クラスが呼び出されるモジュールが「admin.py」ならテンプレートフォルダは「template_admin」、それ以外なら「template」とすること。
「utils.py」ソースの7行目の
self.__module__
で呼び出し元のモジュール名が取れる。
さらにこの行は三項演算子で
if self.__module__ == 'admin':
    template_dir = 'template_admin'
else:
    template_dir = 'template'
と同じ意味。



ちなみに表現は何も変わっていない。
スッキリした分、1歩進んだというしておくか。。。


| Google App Engine | Comment:2 |
コメント
Keydren
I never thought I would find such an eevrdayy topic so enthralling!
I never thought I would find such an eevrdayy topic so enthralling!
| | 2012/02/01 09:47:21
wkeqyvko
BdBENJ <a href="http://iyxnsrvvrtty.com/">iyxnsrvvrtty</a>
BdBENJ <a href="http://iyxnsrvvrtty.com/">iyxnsrvvrtty</a>;
| | 2012/02/02 01:25:04
コメント投稿












画像リロード
*半角の小英字、数字で構成されています