conta's diary

思ったこと、やったことを書いてます。 twitter: @conta_

SQLAlchemyで動的にテーブルを作る

Base.create_all(engine)とすると定義されてるテーブルが全部作られちゃう。
定義してあるけど後でテーブルを動的に作りたい!と思ってやってみた。
一応動いたけど正しいのかどうかは不明。。。

リファレンスに、

Base = declarative_base()
class TestInfo(Base):
    ...

みたいに作ったクラスの中には__table__という属性が作られるよーと、
書いてあった(http://docs.sqlalchemy.org/en/rel_0_7/orm/tutorial.html)

>>> User.__table__ 
Table('users', MetaData(None),
            Column('id', Integer(), table=<users>, primary_key=True, nullable=False),
            Column('name', String(), table=<users>),
            Column('fullname', String(), table=<users>),
            Column('password', String(), table=<users>), schema=None)

これを使って、

"Creating and Dropping Database Tables" http://docs.sqlalchemy.org/en/rel_0_7/core/schema.html#metadata-describing

"Column, Table, MetaData API" http://docs.sqlalchemy.org/en/latest/core/schema.html?highlight=table#sqlalchemy.schema.Table

のところを見つつ、書いてみた。

models.py

モデルを定義する。

Base = declarative_base()
class TestInfo(Base):

    __tablename__ = 'test_info'
    info_name = Column(String(128), primary_key=True)
    description = Column(String(256))

    def __init__(self, info_name, description):
        self.info_name = info_name
        self.description = description

    def __repr__(self):
        return "<TestInfo('%s','%s')>" % (self.info_name, self.description)

db.py

この中でTableを持ってきて、名前を変更してcreateしてる。

def init_db():
    image_info = models.TestInfo.__table__
    image_info.name = 'test001'
    image_info.create(engine)

engine_str = 'mysql+mysqldb://%s:%s@%s:%d/%s?charset=utf8' \
    % (user, password, host, port, db_name)

engine = sqlalchemy.create_engine(engine_str, echo=True)

if __name__ == '__main__':
    init_db(engine)

実行

実行結果はこんな感じ。

$python db.py
mysql+mysqldb://root:root@localhost:3306/test?charset=utf8
2012-07-04 15:32:31,059 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2012-07-04 15:32:31,059 INFO sqlalchemy.engine.base.Engine ()
2012-07-04 15:32:31,061 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'character_set%%'
2012-07-04 15:32:31,061 INFO sqlalchemy.engine.base.Engine ()
2012-07-04 15:32:31,061 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
2012-07-04 15:32:31,061 INFO sqlalchemy.engine.base.Engine ()
2012-07-04 15:32:31,062 INFO sqlalchemy.engine.base.Engine SHOW COLLATION
2012-07-04 15:32:31,062 INFO sqlalchemy.engine.base.Engine ()
2012-07-04 15:32:31,066 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2012-07-04 15:32:31,066 INFO sqlalchemy.engine.base.Engine ()
2012-07-04 15:32:31,068 INFO sqlalchemy.engine.base.Engine 
CREATE TABLE test001 (
        ...
)

”CREATE TABLE test001”になった( ・∀・)

でもこれ使い方おかしいかもしれない。