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

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

前回で書いたようにテンプレートからモデルクラスのメソッドを使うとパフォーマンスが悪くなるので、テンプレートに渡す値を全てディクショナリにしてみようと思う。





結構大幅に変更になるのでまずは変更後のソースを晒してみる。

/admin.py
import logging
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from model import Entry, Category
import utils

class EntryList(webapp.RequestHandler):
    def get(self):
        entries = []
        for entry in Entry.all().order('-created_at'):
            entries.append({
                'key': str(entry.key()),
                'title': entry.title,
                'created_at': utils.to_jst(entry.created_at),
                'categories': entry.get_entry_categories()
            })
        utils.render(self, 'template_admin/entries/index.html', {'entries': Entry.get_entries()})

class EntryNew(webapp.RequestHandler):
    def get(self):
        categories = []
        for category in Category.all().order('-created_at'):
            categories.append({
                'key': str(category.key()),
                'name': category.name,
                'created_at': utils.to_jst(category.created_at)
            })
        utils.render(self, 'template_admin/entries/new.html', {'categories': categories})

    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):
    def get(self, key):
        entry = db.get(db.Key(key))
        categories = []
        for category in Category.all().order('-created_at'):
            categories.append({
                'key': str(category.key()),
                'name': category.name,
                'select': str(category.key()) in entry.categories
            })
        entry = {
            'key': str(entry.key()),
            'title': entry.title,
            'body': entry.body,
            'categories': categories
        }
        utils.render(self, 'template_admin/entries/edit.html', {'entry': entry})

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

class CategoryList(webapp.RequestHandler):
    def get(self):
        categories = []
        for category in Category.all().order('-created_at'):
            categories.append({
                'key': str(category.key()),
                'name': category.name,
                'created_at': utils.to_jst(category.created_at)
            })
        utils.render(self, 'template_admin/categories/index.html', {'categories': categories})

class CategoryNew(webapp.RequestHandler):
    def get(self):
        utils.render(self, 'template_admin/categories/new.html')

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

class CategoryEdit(webapp.RequestHandler):
    def get(self, key):
        category = db.get(db.Key(key))
        category = {
            'key': str(category.key()),
            'name': category.name
        }
        utils.render(self, 'template_admin/categories/edit.html', {'category': category})

    def post(self, key):
        category = db.get(db.Key(key))
        category.name = self.request.get("name")
        category.put()
        logging.info(category.updated_at)
        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/")
/model.py
from google.appengine.ext import db
import logging
import utils

class Entry(db.Model):
    title = db.StringProperty()
    body = db.TextProperty()
    categories = db.StringListProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)

    def comments(self):
        return Comment.all().ancestor(self).order('created_at')

    def get_entry_categories(self):
        categories = []
        try:
            for category in db.get(self.categories):
                categories.append({
                    'key': str(category.key()),
                    'name': category.name,
                    'updated_at': utils.to_jst(category.updated_at),
                    'created_at': utils.to_jst(category.created_at)
                })
            return categories
        except:
            return categories

class Comment(db.Model):
    comment = db.TextProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)

class Category(db.Model):
    name = db.TextProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)
だいぶ変更したのでかなり飛躍した感がありますが、要はテンプレートの値としてモデルインスタンスを渡すのではなく、すべてディクショナリで整形してから渡すようにしたということです。記事Entryの登録カテゴリーもメソッド化してますが、ディクショナリが配列となったリストを返しています。

この変更を行ってすぐ気づくのは記事のリストをとったり、カテゴリーのリストをとったりするのはよくある処理なので冗長になっているという点です。なので記事の一覧を取得したい場合は「Entry」クラスのメソッドで「get_entries()」とかでリストがとれるように改変したらより「admin.py」のソースがスッキリしそうですね。
早速やってみます。
/admin.py
import logging
from google.appengine.ext import webapp
from google.appengine.ext import db
from model import Entry, Category
import utils



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

class EntryList(webapp.RequestHandler):
    def get(self):
        utils.render(self, 'template_admin/entries/index.html', {'entries': Entry.get_entries()})

class EntryNew(webapp.RequestHandler):
    def get(self):
        categories = []
        for category in Category.all().order('-created_at'):
            categories.append({
                'key': str(category.key()),
                'name': category.name,
                'created_at': utils.to_jst(category.created_at)
            })
        utils.render(self, 'template_admin/entries/new.html', {'categories': categories})

    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):
    def get(self, key):
        utils.render(self, 'template_admin/entries/edit.html', {'entry': Entry.get_entry(key)})

    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):
    def get(self):
        utils.render(self, 'template_admin/categories/index.html', {'categories': Category.get_categories()})

class CategoryNew(webapp.RequestHandler):
    def get(self):
        utils.render(self, 'template_admin/categories/new.html')

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

class CategoryEdit(webapp.RequestHandler):
    def get(self, key):
        utils.render(self, 'template_admin/categories/edit.html', {'category': Category.get_category(key)})

    def post(self, key):
        category = db.get(db.Key(key))
        category.name = self.request.get("name")
        category.put()
        logging.info(category.updated_at)
        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/")
/model.py
from google.appengine.ext import db
import logging
import utils

class Entry(db.Model):
    title = db.StringProperty()
    body = db.TextProperty()
    categories = db.StringListProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)

    @classmethod
    def get_entry(self, key, admin=None):
        entry = db.get(db.Key(key))
        entry = {
            'key': str(entry.key()),
            'title': entry.title,
            'body': entry.body,
            'categories': Category.get_categories(entry)
        }
        return entry

    @classmethod
    def get_entries(self):
        entries = []
        for entry in self.all().order('-created_at'):
            entries.append({
                'key': str(entry.key()),
                'title': entry.title,
                'created_at': utils.to_jst(entry.created_at),
                'categories': entry.get_entry_categories()
            })
        return entries

    def get_entry_categories(self):
        categories = []
        try:
            for category in db.get(self.categories):
                categories.append({
                    'key': str(category.key()),
                    'name': category.name,
                    'updated_at': utils.to_jst(category.updated_at),
                    'created_at': utils.to_jst(category.created_at)
                })
            return categories
        except:
            return categories

    def comments(self):
        return Comment.all().ancestor(self).order('created_at')



class Comment(db.Model):
    comment = db.TextProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)



class Category(db.Model):
    name = db.TextProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)

    @classmethod
    def get_category(self, key):
        category = db.get(db.Key(key))
        category = {
            'key': str(category.key()),
            'name': category.name,
            'updated_at': utils.to_jst(category.updated_at),
            'created_at': utils.to_jst(category.created_at)
        }
        return category

    @classmethod
    def get_categories(self, entry=None):
        categories = []
        for category in self.all().order('-created_at'):
            if entry is None:
                select = False
            else:
                select = str(category.key()) in entry.categories
            categories.append({
                'key': str(category.key()),
                'name': category.name,
                'updated_at': utils.to_jst(category.updated_at),
                'created_at': utils.to_jst(category.created_at),
                'select': select
            })
        return categories
「admin.py」のコード量が減って「model.py」のコード量が多くなって大体とんとんぐらいになりました。まぁその分「admin.py」のソースがすっきりしたような気がします。

「put()」と「delete()」は?
そうですね、ここもまとめれそうですが、次回にまわしましょう。
今気づいたんですが、削除の際に自分自身だけでなく関係のエンティティも変更、削除する処理を入れないといけないですし、そろそろ逃げてきたバリデーションも考えなくちゃということで。


| Google App Engine | Comment:0 |
コメント投稿












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