11

私は、ユーザーがデータベースによって自動的にサポートされるいくつかのクラスを簡単に宣言できるライブラリに取り組んでいます。つまり、コードのどこかに隠されている

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class LibraryBase(Base):
    # important library stuff

そして、ユーザーはそれを行う必要があります

class MyStuff(LibraryBase):
    # important personal stuff

class MyStuff_2(LibraryBase):
    # important personal stuff

mystuff = MyStuff()
Library.register(mystuff)
mystuff.changeIt() # apply some changes to the instance
Library.save(mystuff) # and save it

# same for all other classes

たとえば、ユーザーがすべてのパーソナル クラスを含む 1 つのファイルを作成し、このファイルをインポートするなどの静的環境では、これは非常にうまく機能します。すべてのクラス名は固定されており、SQLAlchemy は各クラスのマッピング方法を認識しています。

インタラクティブな環境では状況が異なります。クラスが 2 回定義される可能性があります。両方のクラスが異なるモジュールを持つ場合があります。それでもSQLAlchemyは文句を言います:

SAWarning: クラス名 'MyStuff' は既にこの宣言ベースのレジストリにあり、< class 'OtherModule.MyStuff' > にマップされています

これに対処する方法はありますか?その定義を新しいものと交換できるように、どうにかしてそのクラスをアンロードできますか?declarative_base

4

3 に答える 3

4

以下を使用できます。

sqlalchemy.orm.instrumentation.unregister_class(cl)
del cl._decl_class_registry[cl.__name__]

最初の行は、未登録のクラスの誤った使用を防ぐことです。2 番目は登録を解除し、警告を防ぎます。

于 2012-12-03T08:59:42.253 に答える
2

どうやら、これでもうまくいくかどうかはわかりませんが、あなたが欲しいのは

sqlalchemy.orm.instrumentation.unregister_class()

http://hg.sqlalchemy.org/sqlalchemy/file/762548ff8eef/lib/sqlalchemy/orm/instrumentation.py#l466

于 2011-03-08T06:13:35.493 に答える
0

私のプロジェクトでは、このソリューションを使用しています。mixin として定義されたライブラリ指定の列と、base を使用した呼び出しdeclared_attrによって作成されたターゲット マッパーにより、完全に機能するマッパーが得られます。type

from sqlalchemy import create_engine, BigInteger, Column
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import declared_attr


Base = declarative_base()


class LibraryBase(object):
    __tablename__ = 'model'

    @declared_attr
    def library_field(self):
        return Column(BigInteger)


class MyLibrary(object):

    @classmethod
    def register(cls, entity):
        tablename = entity.__tablename__
        Mapper = type('Entity_%s' % tablename, (Base, LibraryBase, entity), {
            '__tablename__': tablename,
            'id': Column(BigInteger, primary_key=True),
        })
        return Mapper

    @classmethod
    def setup(cls):
        Base.metadata.create_all()


class MyStaff(object):
    __tablename__ = 'sometable1'

    @declared_attr
    def staff_field(self):
        return Column(BigInteger)

    def mymethod(self):
        print('My method:', self)


class MyStaff2(MyStaff):
    __tablename__ = 'sometable2'


if __name__ == '__main__':
    engine = create_engine('sqlite://', echo=True)
    Base.metadata.bind = engine
    Session = scoped_session(sessionmaker(bind=engine))
    session = Session()

    # register and install
    MyStaffMapper = MyLibrary.register(MyStaff)
    MyStaffMapper2 = MyLibrary.register(MyStaff2)
    MyLibrary.setup()

    MyStaffMapper().mymethod()
    MyStaffMapper2().mymethod()

    session.query(MyStaffMapper.library_field) \
        .filter(MyStaffMapper.staff_field != None) \
        .all() 
于 2013-06-10T13:22:12.030 に答える