2017-11-18 3 views
0

インデックスを持つミックスインがある場合、そのミックスインを継承しているモデルに追加のインデックスを追加するにはどうすればよいですか?インデックス名がidx__TABLENAME__COLUMNの場合、mixinはTABLENAMEを取得できません。 mixinに__tablename__が指定されている場合、重複するインデックス名が発生します。sqlalchemyミックスインからインデックスを継承して追加する

例コードは次のとおりです。あなたは、サブクラスのコンテキスト内で基底クラスのメソッドにアクセスするためにsuperを使用する必要がミックスインからインデックスを組み込むこと

import sqlalchemy as sql 
from sqlalchemy import Column, Index, String, Integer 
from sqlalchemy.ext.declarative import declared_attr, declarative_base 


Base = declarative_base() 

class MixinOwner(object): 
    id = Column('id', Integer, primary_key=True) 
    owner = Column('owner', String) 

    @declared_attr 
    def __table_args__(cls): 
     return (Index('idx__%s__owner' % cls.__tablename__, 'owner'),) 


class Letter(MixinOwner, Base): 
    __tablename__ = 'letter' 
    a = Column('a', String) 
    b = Column('b', String) 

    @declared_attr 
    def __table_args__(cls): 
     mixin_indexes = list(MixinOwner.__table_args__) # <--- Error (MixinOwner does not have attribute __tablename__) 
     mixin_indexes.extend([ 
      Index('idx__letter__a', 'a'), 
      Index('idx__letter__b', 'b'), 
     ]) 
     return tuple(mixin_indexes) 


class Word(MixinOwner, Base): 
    __tablename__ = 'word' 
    apple = Column('apple', String) 
    banana = Column('banana', String) 

    @declared_attr 
    def __table_args__(cls): 
     mixin_indexes = list(MixinOwner.__table_args__) 
     mixin_indexes.extend([ 
      Index('idx__word__apple', 'apple'), 
      Index('idx__word__banana', 'banana'), 
     ]) 
     return tuple(mixin_indexes) 




engine = sqlalchemy.create_engine('sqlite:///:memory:') 
engine.connect() 

Base.metadata.bind = engine 
Base.metadata.create_all() 

Session = sqlalchemy.orm.sessionmaker(bind=engine) 
session = Session() 

答えて

0

。私が提起した元の質問を解決するこの修正に加えて、(元の質問に設定されたように)複数のミックスインからインデックスを組み込む方法もあります。次のコードはこの大きな問題についても説明しています。解決策は、MROを反復して、モデルのコンテキストで各基本クラスに対して__table_args__を取得することです。

import sqlalchemy as sql 
from sqlalchemy import Column, Index, String, Integer, Date 
from sqlalchemy.ext.declarative import declared_attr, declarative_base 


Base = declarative_base() 

class MixinOwner(object): 
    id = Column('id', Integer, primary_key=True) 
    owner = Column('owner', String) 

    @declared_attr 
    def __table_args__(cls): 
     return (Index('idx__%s__owner' % cls.__tablename__, 'owner'),) 

class MixinDate(object): 
    date = Column('date', Date) 

    @declared_attr 
    def __table_args__(cls): 
     return (Index('idx__%s__date' % cls.__tablename__, 'date'),) 



# single mixin inheritance (original question) -- use super(cls, cls) 
class Word(MixinOwner, Base): 
    __tablename__ = 'word' 
    apple = Column('apple', String) 
    banana = Column('banana', String) 

    @declared_attr 
    def __table_args__(cls): 
     mixin_indexes = list((super(cls, cls).__table_args__)) 
     mixin_indexes.extend([ 
      Index('idx__word__apple', 'apple'), 
      Index('idx__word__banana', 'banana'), 
     ]) 
     return tuple(mixin_indexes) 


# multiple mixin iheritance (not in original question) 
# iterate through __mro__ and aggregate __table_args__ from each base 
class Letter(MixinOwner, MixinDate, Base): 
    __tablename__ = 'letter' 
    a = Column('a', String) 
    b = Column('b', String) 

    @declared_attr 
    def __table_args__(cls): 
     mixin_indexes = [] 
     for base_class in cls.__mro__: 
      try: 
       mixin_indexes.extend(super(base_class, cls).__table_args__) 
      except AttributeError: 
       pass 
     mixin_indexes.extend([ 
      Index('idx__letter__a', 'a'), 
      Index('idx__letter__b', 'b'), 
     ]) 
     return tuple(mixin_indexes) 




engine = sql.create_engine('sqlite:///:memory:') 
engine.connect() 

Base.metadata.bind = engine 
Base.metadata.create_all() 

Session = sql.orm.sessionmaker(bind=engine) 
session = Session() 
関連する問題