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

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

バリデーションとかソースを非冗長化するとかさきに片付けたいところですが、もう少しそこは目をつぶってブログとしての機能をまがりなりにも動く形でみれるように先に勧めます。
ブログ記事にはカテゴリー分けが必須ですし、当ブログでもその機能があるので今回はそれを実装してみます。




現ブログではいち記事に対していちカテゴリーしか選択できないようになっていますが、どうせならカテゴリーを複数選択できるように変更してみます。

ブログのカテゴリーの特性として増えることはあっても減ることはないでしょう。要するに一旦追加されればそのままであるのが一般的だと思います。恐らく変更もほぼないと思います。

ただし「ほぼない」からといってそれらの機能を用意する必要がないということにはなりません。どちらかというとデータのもたせ方や関連性の作り方に関係してくると言えるでしょう。

難しい部分は後回しにして、まずはカテゴリーのCRUDを作ってみます。
モデルクラスは以下のとおり。
class Category(db.Model):
    name = db.StringProperty()
    updated_at = db.DateTimeProperty(auto_now=True)
    created_at = db.DateTimeProperty(auto_now_add=True)
あまり深く考えません。これも適当です。とりあえずカテゴリー名だけあればいい。順番とかどうすんの?とか勿論あとあと。

管理画面に記事CRUDと同じ要領で追加します。ほぼ全てコピー。ほとんど同じなので。
/main.py
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)
ルーティングにカテゴリーの分を足します。

/model.py
class Category(db.Model):
    name = 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)
上記を足します。

/admin.py
class CategoryList(webapp.RequestHandler):
    def get(self):
        categories = Category.all().order('-created_at')
        template_values = {
            'categories': categories
        }
        path = os.path.join(os.path.dirname(__file__), 'template_admin/categories/index.html')
        self.response.out.write(template.render(path, template_values))

class CategoryNew(webapp.RequestHandler):
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'template_admin/categories/new.html')
        self.response.out.write(template.render(path, template_values))

    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))
        template_values = {
            'category': category
        }
        path = os.path.join(os.path.dirname(__file__), 'template_admin/categories/edit.html')
        self.response.out.write(template.render(path, template_values))

    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/")
上記ハンドラー群を足します。モデル「Category」クラスのインポートを書くのを忘れずに。まぁエラーで気づきますけどね。

/template_admin/categories/edit.html
{% extends "../layout.html" %}

{% block script_function %}{% endblock %}

{% block h1 %}編集{% endblock %}

{% block contents %}
  <form action="/admin/category/edit/{{ category.key }}" method="post">
  ■カテゴリー名
  <input type="text" name="name" value="{{ category.name|escape }}" size="40" />
  <input type="submit" value="変更する" />
  </form>
{% endblock %}

/template_admin/categories/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 category in categories %}
  <h2>{{ category.name|escape }}</h2>
  <p>{{ category.jst_created_at|date:"Y年m月d日 H時i分" }}</p>
  <p>[<a href="/admin/category/edit/{{ category.key }}">編集</a>][<a href="/admin/category/delete/{{ category.key }}" onclick="return deletecheck()">削除</a>]</p>
  <hr />
{% endfor %}
{% endblock %}

/template_admin/categories/new.html
{% extends "../layout.html" %}

{% block script_function %}{% endblock %}

{% block h1 %}新規登録{% endblock %}

{% block contents %}
  <form action="/admin/category/new" method="post">
  ■カテゴリー名
  <input type="text" name="name" value="" size="40" />
  <input type="submit" value="追加する" />
  </form>
{% endblock %}


テンプレートも記事フォルダをまるごとコピーして中身を少し書き換えるだけでOKです。時間にしてそれほどかかりません。

現時点では登録した順番にしかカテゴリーは並びません。やはり並び替えはないといけませんのでこれは後の課題としておきます。

さて、カテゴリーのCRUDがいちおうはできましたが、この状態ではまったくスタンドアローンで用を足さないですね。
ここで登録したカテゴリーを記事の方で複数選択できるようにしなければなりません。さてどうしたものか…

いち記事に対していちカテゴリーを選択するのであれば記事にひとつプロパティを作ってキーでも入れておけば容易に実現できそうですが、複数選択できてなおかつ編集もできなくてはならないとなればひとつハードルがあがります。
ということでこれしか思いつきませんが、ListProperty()を使ってリスト化した複数のキーを持つことでなんとかできないかなーと思ってやってみます。

う〜ん長くなりそうなので次回を待て。

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












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