IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

Google App Engine で Tropy っぽいやつ作ってみた

Google App Engine の SDK で

何か作ってみよう!
というわけで、 Tropy みたいなやつを作ってみる
python で 20 行以上のプログラムを書くのはたぶん初めてだ

Tropy とは

以下が詳しいです。
Tropyとは - はてなキーワード
ちなみに、以下のスクリーンショットは id:naoya さんが作った Tropy のクローンの Haropy です。

で、僕もそんな感じのものを作ってみた

ソースを晒しておきます。

ファイル構成
PyGropy
|-- app.yaml
|-- edit.html
|-- entry.html
`-- pygropy.py
app.yaml

設定ファイル

application: pygropy
version: 1
runtime: python
api_version: 1

handlers:
- url: /.* 
  script: pygropy.py
pygropy.py

コントローラとモデルのプログラム

import os
from random import random
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from pprint import pprint

# models
class Entry(db.Model):
    title     = db.StringProperty  (required=True)
    body      = db.StringProperty  (required=True)
    timestamp = db.DateTimeProperty(required=True, auto_now=True)

    def to_hash(self):
        return {
                'id': self.key().id(),
                'title': self.title,
                'body': self.body,
                'timestamp': self.timestamp,
            }

# controllers
class MainPage(webapp.RequestHandler):
    def get(self):
        redirect_random_id(self)

class EntryPage(webapp.RequestHandler):
    def get(self):
        id = self.request.get('id');
        if id:
            entry = Entry.get_by_id(int(id))
            path = os.path.join(os.path.dirname(__file__), 'entry.html')
            self.response.out.write(template.render(path, entry.to_hash())) 
        else:
            redirect_random_id(self)

class EditPage(webapp.RequestHandler):
    def post(self):
        id = self.request.get('id');
        title = self.request.get('title');
        body = self.request.get('body');
        entry = False

        if id:
            entry = Entry.get_by_id(int(id))

        if not(entry):
            entry = Entry(title=title, body=body)
        else:
            entry.title = title;
            entry.body = body;

        id = entry.put().id()
        self.redirect('/entry?id=' + str(id))

    def get(self):
        id = self.request.get('id');
        entry = False

        if id:
            entry = Entry.get_by_id(int(id))

        if entry:
            vars = entry.to_hash()
        else:
            vars = {}

        path = os.path.join(os.path.dirname(__file__), 'edit.html')
        self.response.out.write(template.render(path, vars)) 

def redirect_random_id(handler):
    count = db.GqlQuery('SELECT * FROM Entry').count();
    if count == 0:
        handler.redirect('/edit')
    else:
        id = int(random() * count) + 1
        handler.redirect('/entry?id=' + str(id))

def main():
    application = webapp.WSGIApplication([('/', MainPage),
                                          ('/edit', EditPage),
                                          ('/entry', EntryPage),
                                         ],
                                         debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()
edit.html

編集用の html のテンプレート

<html>
    <head>
        <title>PyGropy ver.0721</title>
    </head>
    <body>
        <form action="/edit" method="post">
            <ul>
                <li><input type="text" name="id" value="{{id|escape}}" /></li>
                <li><input type="text" name="title" value="{{title|escape}}" /></li>
                <li><textarea name="body">{{body|escape}}</textarea></li>
                <li>{{timestamp|escape}}</li>
                <li><input type="submit" name="_submit" value="submit" /></li>
                <li><a href="/">random</a></li>
            </ul>
        </form>
    </body>
</html>
entry.html

表示用の html のテンプレート

<html>
    <head>
        <title>PyGropy ver.0721</title>
    </head>
    <body>
        <ul>
            <li>{{id|escape}}</li>
            <li>{{title|escape}}</li>
            <li>{{body|escape}}</li>
            <li>{{timestamp|escape}}</li>
            <li><a href="/edit?id={{id|escape}}">edit</a></li>
            <li><a href="/">random</a></li>
        </ul>
    </body>
</html>

とりあえず、以下のコマンドでテストサーバが動きます。

$ dev_appserver.py ディレクトリ名
INFO     2008-04-09 00:48:48,665 appcfg.py] Checking for updates to the SDK.
INFO     2008-04-09 00:48:49,392 appcfg.py] The SDK is up to date.
INFO     2008-04-09 00:48:49,401 dev_appserver_main.py] Running application pygropy on port 8080: http://localhost:8080

動かしてみる


わーいわーい動いたー
あれ、複数行入れるとエラーになるなあ。たぶん、モデル定義のといに型の指定を間違えたっぽい><
でも、まあ、そこは本質的な作業じゃないので間違えたままにしておきます。
あれ、タイムスタンプもおかしいな。まあいいや。