迁移pylonsbook chapter 8到pylons1.0

Sun 12 September 2010
  • 手艺 tags:
  • pylons
  • python
  • sqlalchemy published: true comments: true

Pylonsbook的第八章,是一个完整的CRUD程序例子。pylons升级到1.0之后,有一些代码不能正常工作了。

首先查看你使用的各种库的版本: paster shell development.ini [cc lang="python"]
import pylons
pylons.__version__
import sqlalchemy
sqlalchemy.__version__
import webhelpers
webhelpers.__version__
[/cc]

Pylons 1.0开始鼓励通过继承Base类的声明式ORM(pylonsbook介绍的是pylons 0.9x,sqlalchemy 0.5x,使用mapper的方式)
对pylons1.0,mode/__init__.py中声明model的代码如下:
[cc lang="python"]
from sqlalchemy import *
from sqlalchemy.orm import relationship

class PageTag(Base):
__tablename__ = 'pagetag'
id = Column('id', Integer, Sequence('pagetag_seq_id', optional=True), primary_key=True)
pageid = Column('pageid', Integer, ForeignKey('page.id'))
tagid = Column('tagid', Integer, ForeignKey('tag.id'))

class Page(Base):
"""docstring for Page"""
__tablename__ = 'page'
id = Column('id', Integer, Sequence('page_seq_id', optional=True), primary_key=True)
content = Column('content', Text, nullable=False)
posted = Column('posted', DateTime, default=now())
title = Column('title', Unicode(255), default=u'Untitled Page')
heading = Column('heading', Unicode(255))

tags = relationship(PageTag, backref='page')
comments = relationship("Comment", backref='page')

class Tag(Base):
"""docstring for Tag"""
__tablename__ = 'tag'
id = Column('id', Integer, Sequence('tag_seq_id', optional=True), primary_key=True)
name = Column('name', Unicode(20), nullable=False, unique=True)

class Comment(Base):
__tablename__ = 'comment'
id = Column('id', Integer, Sequence('comment_seq_id', optional=True), primary_key=True)
content = Column('content', Text, default=u'')
name = Column('name', Unicode(255))
email = Column('email', Unicode(255), nullable=False)
created = Column('created', TIMESTAMP, default=now())
pageid = Column(Integer, ForeignKey('page.id'))

[/cc]

init_model 方法的内容也不相同,但是对Session的配置都是在Session.configure里进行。 如果设置autocommit=True,即使设置了autoflush=True仍然需要Session.flush()一下才能把变更写入数据库。否则,则需要显示调用Session.commit()

在写controller的部分,pylonsbook大量用了
[cc lang="python"]
page_q = model.meta.Session.query(model.Page)
c.page = page_q.get(int(id))
[/cc]


[cc lang="python"]
page_q = model.meta.Session.query(model.Page)
c.page = page_q.filter_by(id=id).first()
[/cc]
在新版本里只需要
[cc lang="python" inline="true"]
c.page=Session.query(model.Page).get(id)
[/cc]
即可。

在模板部分,pylons现在默认不依赖formbuild,所以文中提到的helper方法要额外安装formbuild库。不过这些也可以用过webhelper来实现,在lib/helpers.py里:
[cc lang="python" inline="true"]
from webhelpers.html.tags import *
[/cc]

在field.html中
[cc lang="html"]

Heading: ${h.text(
"heading"
)}

Title: ${h.text(
"title"
)}

Content: ${h.textarea(
"content", cols=40, rows=10
)}

[/cc]

模板中一个非常常用的方法url_for在pylons1.0里被改为pylons.url,需要修改/lib/helpers.py
[cc lang="python" inline="true"]
from pylons import url
[/cc]

书中所有的重定向都是直接设置response相关属性实现的,实际可以用redirect,结合url:
[cc lang="python" inline="true"]
redirect(url(controller='page', action='view', id=page.id))
[/cc]

分页部分,如果你使用的是sqlalchemy 0.6的话,随pylons 1.0发布的Webhelpers 0.6还不支持 sqlalchemy 0.6的query object,需要手动升级到1.2. (easy_install -U webhelpers)

最后关于flash状态,webhelpers里有一个专门的实现,不过还是不太好用: http://pylonshq.com/docs/en/1.0/thirdparty/webhelpers/pylonslib/

The post is brought to you by lekhonee v0.7