ブログをGoogle App Engineへ移行してみる10
2010/12/27 21:16:20
管理画面で記事を簡易ながらも管理できるようになったので、ブログ表示部分をつくってコメントをつけれるようにして「らしく」していきます。
「/」で記事一覧が出るようにします。ページ処理やアーカイブや検索はどうするんだと頭をもたげますが、そういう邪念はとりはらって未来の自分に託します。
なにごともひとつずつ。いっぺんにたくさんしようとしてもできませんので。
新しいルーティングが必要になりますね。これからもどんどん増えそうなので少し「main.py」を眺めてどうすれば拡張しやすいかしばし考えます。
管理記事一覧は「EntryListクラス」、表示記事一欄も「EntryListクラス」。にはできません。
では
管理記事一覧 → AdminEntryList
表示記事一欄 → EntryList
でどうでしょうか?
なんか名前が長くてあまりよくなさそうですね…
いっそ管理を構成するクラスを別ファイル「admin.py」とかにしてみてはどうでしょうか?
別ファイルになれば名前空間も別にできるので同じクラス名が使えます。
よさそうですね。早速やってみます。
Entryモデルはどちらからも参照されますのでモデルはモデルでこれも別ファイルする必要がありそうです。
admin.py
model.py
main.py
この状態では管理の記事一覧も表示の記事一覧も同じテンプレートを見ていますので同じものが表示されています。
さてこれをなんとかしなくてはいけませんね。
さっきのクラス名の問題と同じで、管理の記事一覧を「admin_index.html」とかは論外なんでファイル名で区分けするのではなくフォルダでわけます。
CSSも分けないのか?と聞かれそうですが、わざわざ「static_admin」とか作って「app.yaml」に書くほどではないと思います。
ではちょっと長いですが、大分内容も編集しましたので、全てのファイルを晒してみましょう。
/admin.py
/model.py
/main.py
/template/layout.html
/template/entries/index.html
/template_admin/layout.html
/template_admin/entries/edit.html
/template_admin/entries/index.html
/template_admin/entries/new.html
ファイル構成なども変わってなんか「らしく」なってきましたね。
表示の記事一覧もできましたし、次回はこれにコメントを投稿できるようにしてみることを考えていきます。
なにごともひとつずつ。いっぺんにたくさんしようとしてもできませんので。
新しいルーティングが必要になりますね。これからもどんどん増えそうなので少し「main.py」を眺めてどうすれば拡張しやすいかしばし考えます。
管理記事一覧は「EntryListクラス」、表示記事一欄も「EntryListクラス」。にはできません。
では
管理記事一覧 → AdminEntryList
表示記事一欄 → EntryList
でどうでしょうか?
なんか名前が長くてあまりよくなさそうですね…
いっそ管理を構成するクラスを別ファイル「admin.py」とかにしてみてはどうでしょうか?
別ファイルになれば名前空間も別にできるので同じクラス名が使えます。
よさそうですね。早速やってみます。
Entryモデルはどちらからも参照されますのでモデルはモデルでこれも別ファイルする必要がありそうです。
admin.py
from google.appengine.ext import webapp
import os
from google.appengine.ext.webapp import template
from model import Entry
class EntryList(webapp.RequestHandler):
def get(self):
entries = Entry.all().order('-created_at')
template_values = {
'entries': entries
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
class EntryNew(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'new.html')
self.response.out.write(template.render(path, template_values))
def post(self):
entry = Entry()
entry.title = self.request.get("title")
entry.body = self.request.get("body")
entry.put()
self.redirect("/admin/")
class EntryEdit(webapp.RequestHandler):
def get(self, key):
entry = db.get(db.Key(key))
template_values = {
'entry': entry
}
path = os.path.join(os.path.dirname(__file__), 'edit.html')
self.response.out.write(template.render(path, template_values))
def post(self, key):
entry = db.get(db.Key(key))
entry.title = self.request.get("title")
entry.body = self.request.get("body")
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/")model.py
from google.appengine.ext import db
import datetime
class Entry(db.Model):
title = db.StringProperty()
body = db.TextProperty()
updated_at = db.DateTimeProperty(auto_now=True)
created_at = db.DateTimeProperty(auto_now_add=True)
def jst_created_at(self):
return self.created_at + datetime.timedelta(hours=9)main.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import os
from google.appengine.ext.webapp import template
import datetime
import admin
from model import Entry
class EntryList(webapp.RequestHandler):
def get(self):
entries = Entry.all().order('-created_at')
template_values = {
'entries': entries
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
application = webapp.WSGIApplication([
('/', EntryList),
('/admin/', admin.EntryList),
('/admin/new', admin.EntryNew),
('/admin/edit/([\w\-]+)', admin.EntryEdit),
('/admin/delete/([\w\-]+)', admin.EntryDelete)
],debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()pyファイルを3つに分けました。今の時点では「static」フォルダ以外のファイルは全て同階層にあります。まだスッキリとはいきませんが、機能的に別ファイルに分かれている感じですね。なんかヒントが見えそうです。根拠ありませんけど。この状態では管理の記事一覧も表示の記事一覧も同じテンプレートを見ていますので同じものが表示されています。
さてこれをなんとかしなくてはいけませんね。
さっきのクラス名の問題と同じで、管理の記事一覧を「admin_index.html」とかは論外なんでファイル名で区分けするのではなくフォルダでわけます。
│ admin.py
│ app.yaml
│ main.py
│ model.py
│
├─static
│ │ all.css
│ │ style.css
│ │
│ └─admin
│ style.css
│
├─template
│ │ layout.html
│ │
│ └─entries
│ index.html
│
└─template_admin
│ layout.html
│
└─entries
edit.html
index.html
new.htmlこんな感じのフォルダ・ファイル構成に変更してみました。これまでの平坦な同階層にあるという構成から大幅に変わりましたよ。まだつたないですが、これで今後の作りをシンプルに拡張していけそうな気がします。CSSも分けないのか?と聞かれそうですが、わざわざ「static_admin」とか作って「app.yaml」に書くほどではないと思います。
ではちょっと長いですが、大分内容も編集しましたので、全てのファイルを晒してみましょう。
/admin.py
from google.appengine.ext import webapp
import os
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from model import Entry
class EntryList(webapp.RequestHandler):
def get(self):
entries = Entry.all().order('-created_at')
template_values = {
'entries': entries
}
path = os.path.join(os.path.dirname(__file__), 'template_admin/entries/index.html')
self.response.out.write(template.render(path, template_values))
class EntryNew(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'template_admin/entries/new.html')
self.response.out.write(template.render(path, template_values))
def post(self):
entry = Entry()
entry.title = self.request.get("title")
entry.body = self.request.get("body")
entry.put()
self.redirect("/admin/")
class EntryEdit(webapp.RequestHandler):
def get(self, key):
entry = db.get(db.Key(key))
template_values = {
'entry': entry
}
path = os.path.join(os.path.dirname(__file__), 'template_admin/entries/edit.html')
self.response.out.write(template.render(path, template_values))
def post(self, key):
entry = db.get(db.Key(key))
entry.title = self.request.get("title")
entry.body = self.request.get("body")
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/")/model.py
from google.appengine.ext import db
import datetime
class Entry(db.Model):
title = db.StringProperty()
body = db.TextProperty()
updated_at = db.DateTimeProperty(auto_now=True)
created_at = db.DateTimeProperty(auto_now_add=True)
def jst_created_at(self):
return self.created_at + datetime.timedelta(hours=9)/main.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import os
from google.appengine.ext.webapp import template
import datetime
import admin
from model import Entry
class EntryList(webapp.RequestHandler):
def get(self):
entries = Entry.all().order('-created_at')
template_values = {
'entries': entries
}
path = os.path.join(os.path.dirname(__file__), 'template/entries/index.html')
self.response.out.write(template.render(path, template_values))
application = webapp.WSGIApplication([
('/', EntryList),
('/admin/', admin.EntryList),
('/admin/new', admin.EntryNew),
('/admin/edit/([\w\-]+)', admin.EntryEdit),
('/admin/delete/([\w\-]+)', admin.EntryDelete)
],debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()/template/layout.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>ブログをGoogle App Engineへ移行してみる</title>
<link rel="stylesheet" type="text/css" href="/static/all.css" />
<link rel="stylesheet" type="text/css" href="/static/style.css" />
{% block script_function %}{% endblock %}
</head>
<body>
<div id="header">
<p>ブログをGoogle App Engineへ移行してみる</p>
<!-- /#header --></div>
<div id="left">
<h1>{% block h1 %}{% endblock %}</h1>
{% block contents %}{% endblock %}
<!-- /#left --></div>
<div id="right">
<!-- /#right --></div>
<div id="footer">
<p>copyright(C)2011 jinlingren.com. All Rights Reserved.</p>
<!-- /#footer --></div>
</body>
</html>/template/entries/index.html
{% extends "../layout.html" %}
{% block script_function %}{% endblock %}
{% block h1 %}投稿一覧{% endblock %}
{% block contents %}
{% for entry in entries %}
<h2>{{ entry.title|escape }}</h2>
<p>{{ entry.jst_created_at|date:"Y年m月d日 H時i分" }}</p>
<p>{{ entry.body|escape }}</p>
<hr />
{% endfor %}
{% endblock %}/template_admin/layout.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>ブログをGoogle App Engineへ移行してみる</title>
<link rel="stylesheet" type="text/css" href="/static/all.css" />
<link rel="stylesheet" type="text/css" href="/static/admin/style.css" />
{% block script_function %}{% endblock %}
</head>
<body>
<div id="header">
<p>ブログをGoogle App Engineへ移行してみる</p>
<!-- /#header --></div>
<div id="left">
<ul>
<li>■記事管理</li>
<li><a href="/admin/new">新規投稿</a></li>
<li><a href="/admin/">投稿一覧</a></li>
</ul>
<!-- /#left --></div>
<div id="right">
<h1>{% block h1 %}{% endblock %}</h1>
{% block contents %}{% endblock %}
<!-- /#right --></div>
<div id="footer">
<p>copyright(C)2011 jinlingren.com. All Rights Reserved.</p>
<!-- /#footer --></div>
</body>
</html>/template_admin/entries/edit.html
{% extends "../layout.html" %}
{% block script_function %}{% endblock %}
{% block h1 %}編集{% endblock %}
{% block contents %}
<form action="/admin/edit/{{ entry.key }}" method="post">
■タイトル
<input type="text" name="title" value="{{ entry.title|escape }}" size="40" />
■内容
<textarea name="body" cols="40" rows="10">{{ entry.body|escape }}</textarea>
<input type="submit" value="変更する" />
</form>
{% endblock %}/template_admin/entries/index.html
{% extends "../layout.html" %}
{% block script_function %}
<script type="text/javascript">
function deletecheck(){
if(window.confirm('本当に削除してもよろしいですか?\nデータは完全に削除されます。')){
return true;
}else{
return false;
}
}
</script>
{% endblock %}
{% block h1 %}投稿一覧{% endblock %}
{% block contents %}
{% for entry in entries %}
<h2>{{ entry.title|escape }}</h2>
<p>{{ entry.jst_created_at|date:"Y年m月d日 H時i分" }}</p>
<p>{{ entry.body|escape }}</p>
<p>[<a href="/admin/edit/{{ entry.key }}">編集</a>][<a href="/admin/delete/{{ entry.key }}" onclick="return deletecheck()">削除</a>]</p>
<hr />
{% endfor %}
{% endblock %}/template_admin/entries/new.html
{% extends "../layout.html" %}
{% block script_function %}{% endblock %}
{% block h1 %}新規投稿{% endblock %}
{% block contents %}
<form action="/admin/new" method="post">
■タイトル
<input type="text" name="title" value="" size="40" />
■内容
<textarea name="body" cols="40" rows="10"></textarea>
<input type="submit" value="投稿する" />
</form>
{% endblock %}ふ〜長い記事になりました。ファイル構成なども変わってなんか「らしく」なってきましたね。
表示の記事一覧もできましたし、次回はこれにコメントを投稿できるようにしてみることを考えていきます。