ブログをGoogle App Engineへ移行してみる15
2011/01/20 21:27:50
前回で書いたようにテンプレートからモデルクラスのメソッドを使うとパフォーマンスが悪くなるので、テンプレートに渡す値を全てディクショナリにしてみようと思う。
結構大幅に変更になるのでまずは変更後のソースを晒してみる。
/admin.py
この変更を行ってすぐ気づくのは記事のリストをとったり、カテゴリーのリストをとったりするのはよくある処理なので冗長になっているという点です。なので記事の一覧を取得したい場合は「Entry」クラスのメソッドで「get_entries()」とかでリストがとれるように改変したらより「admin.py」のソースがスッキリしそうですね。
早速やってみます。
/admin.py
「put()」と「delete()」は?
そうですね、ここもまとめれそうですが、次回にまわしましょう。
今気づいたんですが、削除の際に自分自身だけでなく関係のエンティティも変更、削除する処理を入れないといけないですし、そろそろ逃げてきたバリデーションも考えなくちゃということで。
/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.pyfrom 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.pyfrom 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()」は?
そうですね、ここもまとめれそうですが、次回にまわしましょう。
今気づいたんですが、削除の際に自分自身だけでなく関係のエンティティも変更、削除する処理を入れないといけないですし、そろそろ逃げてきたバリデーションも考えなくちゃということで。