Pylons+memcacheDB...新規作成フォーム
まずは電話帳データを登録するフォームから作っていく。
phonebook/lib/helpers.py
from formbuild.helpers import field from formbuild import start_with_layout as form_start, end_with_layout as form_end from webhelpers.html.tags import * from routes import url_for
Pylonsはフォーム部品の再利用も簡単。
phonebook/templates/derived/phone/fields.html
${h.field( "Mobile Number", h.text(name = 'mobile_number'), required = False, )} ${h.field( "Name", h.text(name = "name"), required = True, )} ${h.field( "Address", h.text(name = "address"), required = False, )} ${h.field( "Home Number", h.text(name = "home_number"), required = False, )} ${h.field( "DOB(yyyymmdd)", h.text(name = "dob"), required = False, )}
phonebook/templates/derived/phone/new.html
<%inherit file="/base/index.html"/> <%namespace file="fields.html" name="fields" import="*"/> <%def name="heading()"> <h1 class="main">Create a New Entry</h1> </%def> ${h.form_start(h.url_for(controller = 'phone', action = 'create'), method = "post")} ${fields.body()} ${h.field(field = h.submit(value = "Create", name="submit"))} ${h.form_end()}
phonebook/controllers/phone.py
def new(self): return render('/derived/phone/new.html')
http://10.10.10.147:5000/phone/new にアクセス。
このままではデータベースに書けないので、Submitされたフォームを処理する部分を記述する。まずその前に、Pylonsにmemcachedbへのアクセス先を登録しておく必要がある。
開発用: Phobook/development.iniの[app:main]部分に以下を記述。
memcachedb.servers = 127.0.0.1:21201
テスト用: Phonebook/test.iniの[app:main]を以下のように記述。
[app:main] use = egg:PhoneBook full_stack = true cache_dir = %(here)s/data beaker.session.key = phonebook beaker.session.secret = hogehogehoge sqlalchemy.url = sqlite:///%(here)s/test.db memcachedb.servers = 127.0.0.1:31201
次に、コントローラ(phone.py)を記述。以下のモジュールを取り込めるようにする。
# for form processing import formencode from formencode import htmlfill import phonebook.model as model from pylons.decorators.rest import restrict from pylons.decorators import validate import memcache import jsonpickle from pylons import config import phonebook.lib.helpers as h
Pylonsのフォームチェックはデコレータを使う。そのデコレータに渡すフォームチェック用クラスを定義。(PhoneControllerの前で)
class NewPhoneForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True mobile_number = formencode.validators.String() name = formencode.validators.String(not_empty = True) address = formencode.validators.String() home_number = formencode.validators.String() dob = formencode.validators.String()
→nameが空の時だけ文句をいうようにした。
memcacheは本来memcached(キャッシュ)にアクセスするためのAPIだが、memcachedbはそのmemcached用APIを「そのまま」使えるようになっている。そのmemcachedbにアクセスするハンドラを確保。(PhoneControllerの中で)
def __init__(self): BaseController.__init__(self) self.mc = memcache.Client([config['app_conf']['memcachedb.servers']], debug = 0)
サブミットされたフォームデータを処理する部分。HTTP GETでのアクセスを拒否し、NewPhoneFormで定義されたフォーム内容チェックが走るようになっている。
@restrict('POST') @validate(schema = NewPhoneForm(), form = 'new') def create(self): phone = model.Phone() for k, v in self.form_result.items(): setattr(phone, k, v) p = jsonpickle.Pickler() self.mc.set(phone.id, p.flatten(phone)) response.status_int = 302 response.headers['location'] = h.url_for(controller = 'phone', action = 'view', id = phone.id) return "Moved temporarily"
書き込んだ後、viewに飛ばしている。そのviewもちゃんとmemcachedbから読み出すように変更しておく必要がある。
def view(self, id): if id is None: abort(404) ser = self.mc.get(id.encode('ascii')) if ser is None: abort(404) u = jsonpickle.Unpickler() c.phone = u.restore(ser) if not isinstance(c.phone, model.Phone): abort(404) return render('/derived/phone/view.html')
templates/derived/phone/view.htmlも更新。
<%inherit file="/base/index.html"/> <%def name = "title()">${c.phone.name}</%def> <%def name = "heading()"><h1>${c.phone.name}</h1></%def> Mobile:${c.phone.mobile_number}<br/> Home: ${c.phone.address}<br/> Address: ${c.phone.home_number}<br/> DOB: ${c.phone.dob}<br/> <%def name = "footer()"> <p> <a href="${h.url_for(controller = 'phone', action = 'list', id = None)}">All Pages</a> |<a href="${h.url_for(controller = 'phone', action = 'new', id = None)}">New Page</a> |<a href="${h.url_for(controller = 'phone', action = 'edit', id = c.phone.id)}">Edit Page</a> |<a href="${h.url_for(controller = 'phone', action = 'delete', id = c.phone.id)}">Delete Page</a> </p> ${parent.footer()} </%def>
http://10.10.10.147:5000/phone/new のフォームに適当な入力をして投稿すると、memcachedbに登録されたデータが表示されるはず。
上記の場合、IDには「8636120904394d85b10b48260f81c4de」が割り当てられている。実際どうなっているか、memcachedbに直接つないで確認してみる。
$ python Python 2.6.4 (r264:75706, Dec 28 2009, 15:52:45) [GCC 4.3.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import memcache >>> mc = memcache.Client(['127.0.0.1:21201'], debug=0) >>> v = mc.get('8636120904394d85b10b48260f81c4de') >>> v {'py/object': 'phonebook.model.Phone', 'name': u'masayang', 'dob': u'19200323', 'mobile_number': u'111-1111-1111', 'address': u'1400 Fashion Island', 'home_number': u'222-2222-2222', '_id': '8636120904394d85b10b48260f81c4de'} >>>