前回、Webアプリケーションをさくっと手軽に構築できてしまう Google App Engine (GAE) を試してみましたが、今回は、もう少しまともなアプリケーションを作ってみます。
作成する前に、つい先日 GAEO が 0.3 にバージョンアップしているようなので、早速最新のリリースを試してみましょう。
バージョンアップ作業は、環境変数のパスを新しいバージョンのものに変更しただけです。
Twitter は、140文字以下の短いメッセージをつぶやきあうシンプルなサービスです。現在とても注目されているサービスですね。
シンプルでわかりやすいですので、今回は Twitter もどきのアプリケーションを作成してみます。
mockker
それでは、Twitter もどきの「mockker」というプロジェクトを作成します。
とりえあず今回は、データの登録ができればOKとします。また、アカウントは Google App Engine の ユーザーサービスを使用し、Google アカウントと連携させます。
gaeo.py mockker
cd mockker
まずは、つぶやきの scaffold を作成します。
gaeogen.py scaffold status create show "text:StringProperty()" "user:UserProperty()" "created_at:DateTimeProperty(auto_now_add=True)"
ルーティング
デフォルトのルートへのルーティングを、welcome/index から status/index へ変更します。
gaeo/dispatch/router.pyclass Router:
""" Handles the url routing... """
class __impl:
def __init__(self):
self.__routing_root = {'controller': 'status',
'action': 'index'}
model
scaffold により、 application/model/status.py が作成されます。
application/model/status.pfrom google.appengine.ext import db
from gaeo.model import BaseModel, SearchableBaseModel
class Status(BaseModel):
created_at = db.DateTimeProperty(auto_now_add=True)
text = db.StringProperty()
user = db.UserProperty()
controller
scaffold により作成された status コントローラを次のように修正します。
application/controller/status.pyimport cgi
import logging
from google.appengine.ext import db
from google.appengine.api import users
from gaeo.controller import BaseController
from model.status import Status
class StatusController(BaseController):
def create(self):
r = Status(
# Uncomment all required properties here.
# text = self.params.get('text', None),
# created_at = self.params.get('created_at', None),
user = users.get_current_user(),
)
for prop in Status.properties():
if prop in self.params:
setattr(r, prop, self.params.get(prop))
r.put()
self.flash['notice'] = u"独り言を更新したよ"
self.redirect('/')
def index(self):
notice = self.flash.get('notice', '')
self.msg = notice
if self.current_user:
query = Status.all().filter('user = ', self.current_user)
query.order("-created_at")
self.result = query.fetch(limit=10)
def show(self):
r = Status.get(self.params.get('id'))
if r:
for prop in Status.properties():
setattr(self, prop, getattr(r, prop))
else:
self.redirect('/')
ユーザー認証のため、base コントローラの before_action を次のように修正します。
これにより、全てのアクションの前にユーザー認証が実行されます。
from google.appengine.api import users
def before_action(self):
self.current_user = users.get_current_user()
if not self.current_user:
self.signed_in = False
self.login_url = users.create_login_url(self.request.uri)
#self.redirect(users.create_login_url(self.request.uri))
else:
self.signed_in = True
self.logout_url = users.create_logout_url(self.request.uri)
self.nickname = self.current_user.nickname()
view
view を次のように修正します。
application/templates/base.html<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="/css/common.css" type="text/css" media="screen" />
{% if signed_in %}
<link rel="stylesheet" href="/css/login.css" type="text/css" media="screen" />
{% endif %}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="/js/application.js"></script>
</head>
<body>
<div id="header">
<div id="header_inner">
<h3><a href="/" title="Mockker">Mockker</a></h3>
{% if signed_in %}
<ul id="nav">
<li><a href="{{ logout_url }}" title="Logout">Logout</a></li>
</ul>
{% else %}
<ul id="nav">
<li><a href="{{ login_url }}" title="Login">Login</a></li>
</ul>
{% endif %}
</div>
</div>
<div id="content">
<div id="content_inner">
{% if msg %}
<div class="flash">
<div class="notice">
<p>{{ msg }}</p>
</div>
</div>
{% endif %}
{% if signed_in %}
<div id="update">
<form method="post" action="/status/create">
<span id="countdown">140</span>
<label for="text">何か言いたいことは?</label>
<textarea id="text" name="text" rows="10" cols="10"></textarea>
<input type="submit" name="update" value="Update" />
</form>
</div>
{% endif %}
{% block content %}{% endblock %}
</div>
</div>
<div id="footer">
<div id="footer_inner">
<div class="column">
<ul>
<li><a href="/" title="Home">Home</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
application/templates/status/index.html
{% extends "../base.html" %}
{% block title %}StatusController#index{% endblock %}
{% block content %}
<div id="statuses">
{% for r in result %}
<div id="status_{{ r.key }}" class="status">
<div class="info">
<p class="who_when">
{{ r.user.nickname }}<br />
{{ r.created_at }}
</p>
<p class="actions">
</p>
</div>
<div class="text">
{{ r.text }}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
あとは、Javascript や CSS などで、見栄えを整えます。
実行
dev_appserver.py .
登録したデータをクリアしたい場合は、「--clear_datastore」オプションをつけて実行します。
dev_appserver.py --clear_datastore .
以上で、自分だけがつぶやくことができる、独り言アプリケーションの完成ですw
次回は、他人のつぶやきを表示できるようにしてみたいと思います。
1 件のコメント:
大変参考になりました。
また、ユーザ登録型アプリケーションの解説を探しておりましたので、続きも期待しております。
コメントを投稿