3

テスト DB で異なる属性を持つように SQLAlchemy 列をオーバーライドしようとしています。基本的に、すべての MySQL テーブルに複合主キー (自動インクリメント BIGINTidと DATETIME ) がありcreate_timeます。単体テストには SQLite を使用したいと考えていますが、調査の結果、このユース ケースでは自動インクリメントは不可能であると確信しました。create_timeMySQL でローリング パーティションを作成する以外に列を使用しないため、単体テストで 2 つの列をオーバーライドして、SQLite と互換性を持たせたいと考えています。注: 私はBase = declarative_base()ルートを使用しており、すべてのモデルが and を継承BaseしていPrimaryKeyMixinます。

私の models.py では、PrimaryKeyMixinすべてのテーブルが継承する mixin を作成しました。すべてのテーブルもコンポーネントを継承TABLE_ARGS__table_args__ます。

TABLE_ARGS = {
    'mysql_engine': 'InnoDB',
    'mysql_charset': 'utf8'
}

class PrimaryKeyMixin:
    id = Column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
    create_time = Column(DATETIME, primary_key=True, default=func.now())

単体テストでは、次のことを行います。

from myapp.models import TABLE_ARGS, PrimaryKeyMixin, Column, INT, DATETIME, func
TABLE_ARGS['sqlite_autoincrement'] = True
PrimaryKeyMixin.id = Column(INT(unsigned=True), primary_key=True, autoincrement=True)
PrimaryKeyMixin.create_date = Column(DATETIME, default=func.now())

TEST_DB = '/tmp/myapp_test.db'
from myapp import db
from myapp.models import Base
db.ENGINE = create_engine(
    'sqlite:///%s' % TEST_DB,
    encoding='utf-8',
)
Base.metadata.drop_all(db.ENGINE)
Base.metadata.create_all(db.ENGINE)

ただし、エンジンに echo=True を追加すると、テーブルごとに PRIMARY_KEY (id, create_time) が作成されます。

4

1 に答える 1

1

このようにしましたか:

Base.metadata = MetaData()

def copy_table(model):
    Table(model.__tablename__, Base.metadata, *change_columns(model.__table__.columns), sqlite_autoincrement=True)

def change_columns(columns):
    new_cols = [column.copy() for column in columns if column.name != 'id' and column.name !='create_time']
    new_cols.append(Column('id', INT(unsigned=True), primary_key=True, autoincrement=True))
    new_cols.append(Column('create_time', DATETIME, default=func.now(), autoincrement=True))
    return new_cols

for model in PrimaryKeyMixin.__subclasses__():
    copy_table(model)
于 2013-07-15T20:56:58.940 に答える