Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 可以在SQLAlchemy中卸载声明性类吗?_Python_Class_Mapping_Sqlalchemy_Declarative - Fatal编程技术网

Python 可以在SQLAlchemy中卸载声明性类吗?

Python 可以在SQLAlchemy中卸载声明性类吗?,python,class,mapping,sqlalchemy,declarative,Python,Class,Mapping,Sqlalchemy,Declarative,我正在开发一个库,在这个库中,用户可以简单地声明几个由数据库自动支持的类。简而言之,代码中隐藏的某个地方 from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class LibraryBase(Base): # important library stuff 然后用户应该这样做 class MyStuff(LibraryBase): # important perso

我正在开发一个库,在这个库中,用户可以简单地声明几个由数据库自动支持的类。简而言之,代码中隐藏的某个地方

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
在静态环境中,例如,用户创建了一个包含所有个人类的文件,并导入了该文件,这非常有效。所有类名都是固定的,SQLAlchemy知道如何映射每个类

在交互式环境中,情况有所不同:现在,类有可能被定义两次。两个类可能有不同的模块;但炼金术仍然会抱怨:

SAWarning:类名“MyStuff”已在此声明性基的注册表中,映射到


有办法解决这个问题吗?我能不能从类的
声明性\u库中卸载一个类,这样我就可以用一个新的定义来交换它的定义呢?

看起来,我不确定这是否有效,但我想你想要的是

sqlalchemy.orm.instrumentation.unregister\u class()

您可以使用:

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

第一行是防止意外使用未注册的类。第二个将取消注册并阻止警告。

在我的项目中,我使用此解决方案。 其中,库指定的列由
声明为mixin\u attr
和由
type
创建的目标映射器使用base调用,因此我拥有完整的函数映射器

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()