SQLAlchemy One to One/One to Many

Data Mappingを以下を参考にしながら書いてみました。

A step-by-step SQLAlchemy tutorial
http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html

まずはコードを貼り付けておきます。
DBはSQLiteを使用し、実際にテーブルを生成せずメモリーの中だけでやっています。
(勉強するときはこれが一番)

それとSQLAlchemyはDataMapperだと思っていたのですが、
なにやら

ActiveMapper - sqlalchemy - Trac
http://www.sqlalchemy.org/trac/wiki/ActiveMapper

という単語が。
英語に明るくないのでよくわかっていませんが…。
DataMapperとActiveRecordのいいとこ取りというところでしょうか。

確かにSQLObjectで出来ることは出来ます、面倒ですけど^^;


from simplejson import *
from sqlalchemy import *

# ActivePython(2.4.3.12)
# SimpleJson(1.3.0)
# SQLAlchemy(0.2.3)
# pysqlite(2.3.1)
SQLite(3.3.6)

def run(stmt):
    rs = stmt.execute()
    for row in rs:
        print row
    else:
        print

#One to One/Many to One

#makeshift->
jsonObj = load(file('twisted_mind.json', 'r'), \
     encoding='utf-8')
#<-makeshift

metadata = BoundMetaData('sqlite:///', echo=False)

#makeshift->
users_table = Table('users', metadata,
    Column('user_id', Integer, primary_key=True),
    Column('user_name', String(32)),
    Column('password', String(32)),)

emails_table = Table('emails', metadata,
    Column('mail_id', Integer, primary_key=True),
    Column('address', String(64)),
    Column('user_id', Integer, ForeignKey('users.user_id')),)

metadata.create_all()

for row in jsonObj['users_table']:
    i = users_table.insert()
    i.execute(
        user_id=row[0],
        user_name=row[1],
        password=row[2])

for row in jsonObj['emails_table']:
    i = emails_table.insert()
    i.execute(
        mail_id=row[0],
        address=row[1],
        user_id=row[2])
#<-makeshift

#users_table = Table('users', metadata, autoload=True)
#emails_table = Table('emails', metadata, autoload=True)

#create_session(echo_uow=True)
session = create_session()

class User(object):
    def __init__(self, user_name, password):
        self.user_id = None
        self.user_name = user_name
        self.password = password
    def __repr__(self):
        pass
    def __call__(self):
        pass

class Email(object):
    def __init__(self, address=None):
        self.mail_id = None
        self.address = address
        self.user_id = None
    def __repr__(self):
        return repr(self.address)

#mapper(User, users_table, properties={
#    'address': relation(mapper(Email, emails_table))})

mapper(Email, emails_table)
mapper(User, users_table, properties={
    'address': relation(Email)})

mike = User(user_name='Mike', password='ekim')
mike.address.append(Email('mike@horizon.com'))
mike.address.append(Email('mike@english.com'))

session.save(mike)
session.flush()

clear_mappers()

# Backreferences
mapper(Email, emails_table)
mapper(User, users_table, properties=dict(
    emails=relation(Email, backref='user'),))

mike = session.query(User).get_by(user_name='Mike')
email = Email('mike@hi.com')
email.user = mike

session.save(mike)
session.flush()

clear_mappers()

mapper(Email, emails_table)
#cascade='all, delete-prphan'
mapper(User, users_table, properties=dict(
    emails=relation(Email,
        backref=backref('user'), cascade='all, delete-orphan', lazy=False)))

mike = session.query(User).get_by(user_name='Mike')

session.delete(mike)
session.flush()

clear_mappers()

#Overriding Column Names
#Deferred Column Loading
mapper(Email, emails_table)
mapper(User, users_table, properties=dict(
    id=users_table.c.user_id,
    name=deferred(users_table.c.user_name),
    emails=relation(Email,
        backref=backref('user'), cascade="all, delete-orphan", lazy=False, uselist=True),))

# user_name -> name
john = session.query(User).get_by(name='John')

"""
>>> john.name
'John'
>>> john.id
2
"""
john.name
john.id

clear_mappers()

run(users_table.select())
run(emails_table.select())

今回からソースのカラーリングが素晴らしいですが、
自力じゃないので、いと悔しいです。

私が愛用しているIDEであるKomodoは自分の使ってるカラーリングで
ソースをHTMLに出力してくれるというすてき機能があることに今日!気付きました。

ActiveState - Komodo IDE Perl Python Tcl PHP XSLT - Dynamic Tools for Dynamic Languages
http://www.activestate.com/Products/Komodo/

emacsとかvimとかtextmateとかを華麗に使いこなすことに挫折した人にはお勧めです(私です。

何もしなくても多機能万歳!コード補完万歳!

Personal版なら3000円弱ですのでおすすめです(ってどこの工作員だ。

追記:2006/06/22修正しました。