読者です 読者をやめる 読者になる 読者になる

0.4.2メモ

SQLAlchemy

0.4.2になってORMの少し挙動が変わっていた。

import datetime
from sqlalchemy import *
from sqlalchemy.orm import *

class Entry(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

class Comment(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

# test用ならばsqlite:///で十分だけれどもmysqlなのはなんとなく
engine = create_engine('mysql://root@localhost/test', echo=True)
metadata = MetaData(engine)

# Blogのエントリ的なテーブル
entry_table = Table('entry', metadata,
                    Column('id', Integer, primary_key=True),
                    Column('title', Unicode, nullable=False),
                    Column('content', Unicode, nullable=False),
                    Column('posted_at', DateTime, default=datetime.datetime.now),
                    )

# エントリに対するコメント的なテーブル
comment_table = Table('comment', metadata,
                    Column('id', Integer, primary_key=True),
                    Column('entry_id', Integer, ForeignKey('entry.id'), nullable=False),
                    Column('content', Unicode, nullable=False),
                    Column('posted_at', DateTime, default=datetime.datetime.now),
                    )
# テーブルがなければ作る
metadata.create_all(checkfirst=True)

def good():
    """
    これは0.4.1でも0.4.2でも動く
    """
    clear_mappers()

    mapper(Entry, entry_table)
    mapper(Comment, comment_table, properties={
        'entry': relation(Entry, backref='comments'),
        })

    sess = create_session(engine, autoflush=True, transactional=True)
    # 新しいエントリとコメントを作る
    entry = Entry(title=u'title', content=u'content')
    comment = Comment(content=u'comment')
    # エントリにコメントを追加
    entry.comments.append(comment)
    # 新規作成したエントリなので、セッションに登録して、
    sess.save(entry)
    # コミット
    sess.commit()

    # いったんセッション管理下のオブジェクトを削除して
    sess.clear()

    # さっきのエントリを取得
    entry2 = sess.query(Entry).get(entry.id)
    # 新しいコメントをもう一つ作り
    comment2 = Comment(content=u'comment2')
    # 追加して
    entry2.comments.append(comment2)
    # コミット
    sess.commit()

def bad():
    """
    これは0.4.2では動かない
    """
    clear_mappers()

    # mapperを定義(backrefを定義していない)
    mapper(Entry, entry_table)
    mapper(Comment, comment_table, properties={
        'entry': relation(Entry),
        })

    sess = create_session(engine, autoflush=True, transactional=True)
    # 適当なエントリを取得して
    entry = sess.query(Entry).first()
    # 新しいコメントを作り、
    comment = Comment(content=u'comment2', entry=entry)
    # 新しいコメントオブジェクトをセッション管理下において
    sess.save(comment)
    # コミット・・・できない!
    sess.commit()

if __name__ == '__main__':
    good()
    bad()