SQLAlchemy重映射类

2024-10-02 08:26:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个问题,我需要重新映射一个类,在数据库中相应的表被修改后(列可以被添加或删除)

最小示例:

from sqlalchemy import MetaData, Column, Integer, Table, ForeignKey
from sqlalchemy.orm import mapper
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
Base.metadata = MetaData()


class TableOne(Base):
    __tablename__ = "tableone"
    id = Column(Integer, primary_key=True)


class DynamicTable(object):
    pass


def get_dynamic_table(columns):
    return Table(
        "dynamictable",
        Base.metadata,
        Column("id", Integer, primary_key=True),
        Column("tableone_id", ForeignKey("tableone.id")),
        *[Column(name, type) for name, type in columns],
    )


config = {}
config["dynamic_columns"] = [("foo", Integer)]
initial_table = get_dynamic_table(config["dynamic_columns"])
mapper(DynamicTable, initial_table)

# Run a lot of queries involving e.g. session.query(getattr(DynamicTable, config[dynamic_columns][0]))

# Change config

config["dynamic_columns"] = [("bar", Integer)]

# .. rebuild dynamictable in backend with new config ...

# Now, DynamicTable doesn't reflect the database table

Base.metadata.remove(initial_table)  # Removes the table from metadata, but not the mapper..
updated_table = get_dynamic_table(config["dynamic_columns"])
mapper(DynamicTable, updated_table) # Raises sqlalchemy.exc.ArgumentError

完全读取错误消息

Traceback (most recent call last):
  File "test.py", line 45, in <module>
    mapper(DynamicTable, updated_table)
  File "<string>", line 2, in mapper
  File "/dist/ella-python/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 694, in __init__
    self._configure_class_instrumentation()
  File "/dist/ella-python/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 1220, in _configure_class_instrumentation
    self.class_)
sqlalchemy.exc.ArgumentError: Class '<class '__main__.DynamicTable'>' 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.

有没有办法重新映射这个(或者可能是所有)表


Tags: columnsinfromconfigbasesqlalchemytablecolumn
1条回答
网友
1楼 · 发布于 2024-10-02 08:26:28

Mapper-类dispose()上有一个未记录的方法。这是在^{}中使用的,它对用法有一些严格的警告,但是下面的似乎有效

from sqlalchemy.orm.mapper import class_mapper
existing_mapper = class_mapper(DynamicTable)
existing_mapper.dispose()

Base.metadata.remove(initial_table)  # Removes the table from metadata, but not the mapper..
updated_table = get_dynamic_table(config["dynamic_columns"])
mapper(DynamicTable, updated_table) # Is now re-mapped

相关问题 更多 >

    热门问题