Plone/SQLAlchemy/orm - How can I remap/unmap a class?

635 Views Asked by At

Using orm, I mapping classes to tables for a Plone Site. However, I am having trouble when I need to change the dsn the engine is using and I think because of my approach, I need to remap a class when to reinitialize the mappings.

class DBManager(Persistant):

    implements(IDBManager)

    def __init__(self):
        self._engine = None
        #...
    #...

    def engine(self):
        if self._engine is None:
            self.initEngine()
        return self._engine

    def initEngine(self):
        self._engine = sa.create_engine(self.dsn,convert_unicode=True,encoding='utf-8')

        metadata = sa.MetaData(self._engine)

        tables = []

        for k,v in self.tableNamePairs():
            tables[k] = sa.Table(v,metadata,autoload=True)

        for k,v in self.tableClassPairings():
            orm.mapper(v,tables[k])

    def reinit(self):
        if self._engine:
            self._engine.dispose() #right function?

        self.initEngine()

Here is an example of a table class.

class IMyType(model.Schema):

    form.hidden(My_ID='hidden')
    My_ID = schema.Int(title=u"My Type ID",
                   description=u"Primary Key",
               )

    title = schema.TextLine(title="My Type Title",
                        description = u"Title of MyType"
               )

class MyType(object):

    implements(IMyType)

    My_ID = None
    title = None

    def __init__(self,My_ID,title):
        self.My_ID = My_ID
        self.title = title

Unfortunately, when initEngine is called from reinit, it gets an error when it tries to map -> orm.mapper(v,tables[k])

The error I get is:

ArgumentError: Class '<class 'my.type.tables.my_type.MyType'>' already has a primary mapper defined.  Use non_primary=True to create a non primary Mapper.  clear_mappers() will remove *all* current mappers from all classes.

The error seems to mean that I need to unmap the class. clear_mappers is unfortunately not a solution. Not only would it get rid of mappers I don't want to get rid of, its supposed to be only used in rare instances of testing according to documentation.

Stopping and restarting the instance of the site I am working on is what I am currently doing, but I would like to just change the DSN without having to restart the instance.

Do I need to store the mappers in a list and somehow set them to None? I tried something like that and it didn't make a difference.

def __init__(self):
    #...
    self.mappers = []

def initEngine(self):
    #...
    for k,v in self.tableClassPairings():
        self.mappers.append(orm.mapper(v,tables[k]))

def reinit(self):
    for i in self.mappers:
        i = None
    #...
    self.initEngine()

Is it possible to unmap/remap the tables or should I just settle for stopping/restarting the instance?

0

There are 0 best solutions below