Python Pylons 一覧系アプリケーションを作る |
(一覧表示、新規登録、編集、削除)のアプリケーションを
作ってみます。
前回作成したモジュールを修正していきます。
コントローラーのpage.pyをこんな感じにしてみました。
#■controllers/hello.py
# -*- coding:utf-8 -*-
import logging
from helloworld.lib.base import *
from helloworld.model import Page
log = logging.getLogger(__name__)
class PageController(BaseController):
def index(self):
"""
登録されているコメント一覧を表示
"""
c.pages = Session.query(Page).all()
return render('/list.mako')
def new(self):
"""
新規登録
"""
return render('/new.mako')
def edit(self, id):
"""
編集
"""
page_q = Session.query(Page)
page = page_q.filter_by(id=id).first()
c.page = page
return render('/edit.mako')
def save(self, id):
"""
保存
"""
page_q = Session.query(Page)
page = page_q.filter_by(id=id).first()
#データが取得できないときは、新規登録
if not page:
dummy = page_q.from_statement("SELECT coalesce(max(id) + 1,1) id FROM pages").first()
page = Page()
#登録されているidの最大値を設定
page.id = dummy.id
Session.clear()
page.title = request.params.get('title','')
page.content = request.params.get('content','')
#トランザクション開始
Session.begin()
#データ編集
Session.add(page)
#トランザクション終了
Session.commit()
redirect_to(action='index')
def destroy(self, id):
"""
データ削除処理
"""
page_q = Session.query(Page)
#ページデータを取得
page = page_q.filter_by(id=id).first()
#トランザクション開始
Session.begin()
#データ削除
Session.delete(page)
#トランザクション終了
Session.commit()
redirect_to(action='index')
saveメソッドのidの最大値を取得するロジックですが、
こんな感じのソースコードにすると・・・
if not page:
page = page_q.from_statement("SELECT coalesce(max(id) + 1,1) id FROM pages").first()
エラー発生!
sqlalchemy.orm.exc.ConcurrentModificationError:
Updated rowcount 0 does not match number of objects updated 1
じゃあ、こんな感じのソースコードにすると・・・
if not page:
dummy = page_q.from_statement("SELECT coalesce(max(id) + 1,1) id FROM pages").first()
page = Page()
page.id = dummy.id
エラー発生!
sqlalchemy.orm.exc.FlushError:
New instance <Page at 0x19bf190> with identity key (<class 'helloworld.model.Page'>, (5,)) conflicts with persistent instance <Page at 0x19bf2b0>
http://d.hatena.ne.jp/perezvon/20080415/1208239112
http://groups.google.com/group/sqlalchemy/browse_thread/thread/ffc34438770dcef2/a0421db34d637b2b
このへんを参考に、Sessionが怪しいのでは?とあたりをつけ
if not page:
page = page_q.from_statement("SELECT coalesce(max(id) + 1,1) id FROM pages").first()
page = Page()
page.id = dummy.id
#とりあえずセッションをクリアしてみる
Session.clear()
これで動いてくれました。
※原理はわかってません。
うーん。どうするのが正解なんだろ?
後はテンプレートたちです。
#■templates/list.mako
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>コメント一覧</title>
</head>
<body>
${h.link_to(u'新規作成', h.url(action="new"))}
<br/>
% for page in c.pages:
<li>
${page.title}
${h.link_to(u'編集', h.url(action="edit", id=page.id))}
${h.link_to(u'削除', h.url(action="destroy", id=page.id), confirm=u'削除してよろしいですか?')}
</li>
% endfor
<br/>
</body>
</html>
#■templates/new.mako
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>新規登録</title>
</head>
<body>
${h.form(h.url(action='save'), method='post')}
タイトル: ${h.text_field('title')}
<br/>
本文:${h.text_area(name='content', rows=7, cols=40)} <br />
${h.submit(u'登録')}
${h.end_form()}
</body>
</html>
#■templates/edit.mako
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${c.page.title}編集</title>
</head>
<body>
${h.form(h.url(action='save', id=c.page.id), method='post')}
タイトル: ${h.text_field('title', value=c.page.title or '')}
<br/>
本文:${h.text_area(name='content', rows=7, cols=40, content=c.page.content or '')} <br />
${h.submit(u'更新')}
${h.end_form()}
</body>
</html>
動作画面はこんな感じです。
■一覧画面
■新規登録画面
■編集画面
■削除