SQLAlchemy: сопоставить таблицу с полуконфигурированным классом - PullRequest
0 голосов
/ 04 октября 2018

У меня есть сценарий использования, в котором я хотел бы иметь возможность частично определить таблицу с помощью декларативного API, а затем добавить некоторые атрибуты столбца, соответствующие первичному ключу, который я автоматически генерирую после определения класса таблицы.

Например, скажем, у меня есть эта таблица в качестве отправной точки:

Base = declarative_base(cls=DeferredReflection)

class my_table(Base):
    __tablename__ = "my_table"
    __table_args__ = {'schema': 'my_schema'}

    @hybrid_property
    def my_attr(self):
        return func.coalesce(self.attr_1, self.attr_2, self.attr_3)

Таблица не имеет первичных ключей, но имеет первичный индекс, который фактически является первичным ключом.SQLAlchemy по умолчанию не использует первичный индекс в качестве первичного ключа.Поэтому я хочу создать первичный ключ из первичного индекса, который уже доступен в таблице.

Вот класс, который я написал для достижения этой цели:

class AddPrimaryKeys():
    '''
    This class provides a function that will automatically add primary key
    definitions using the established primary index.
    '''
    def __init__(self, inspector):
        self.inspector = inspector

    def __call__(self, table, metadata):
        pkey_cols = self.__build_pkey_from_index(table)
        return self.__add_primary_keys(table, pkey_cols, metadata)

    def __build_pkey_from_index(self, table):
        tablename = table.__tablename__
        schema = table.__table_args__['schema']
        indices = self.inspector.get_indexes(tablename, schema=schema)
        pkey_info = self.__get_column_info(tablename, schema, indices)
        pkey_cols = self.__build_columns(pkey_info, table)
        return pkey_cols

    def __get_column_info(self, tablename, schema, indices):
        columns = self.inspector.get_columns(tablename, schema=schema)
        index_names = indices[0]['column_names']
        pkey_info = []
        for c in columns:
            if c['name'] in index_names:
                pkey_info.append((c['name'], c['type']))
        return pkey_info

    def __build_columns(self, pkey_info, table):
        pkey_cols = []
        for key_name, key_type in pkey_info:
            column = Column(key_name, key_type, primary_key=True)
            pkey_cols.append(column)
        print(pkey_cols)
        return pkey_cols

    def __add_primary_keys(self, table, pkey_cols, metadata):
        tablename = table.__tablename__
        schema = table.__table_args__['schema']
        table_map = Table(name=tablename, metadata=metadata, schema=schema, *pkey_cols)
        # properties={'primary_key':pkey_cols}
        # mapper(table, table_map, properties=properties)
        mapper(table, table_map)
        return metadata

Я называю класс следующим образом:

insp = inspect(td_engine)
from lib.pkey_lookup import AddPrimaryKeys
add_pkeys = AddPrimaryKeys(insp)
add_pkeys(my_table, Base.metadata)

Вот как может выглядеть список столбцов:

[Column('some_attr', DECIMAL(precision=18), table=None, primary_key=True, nullable=False), Column('another_attr', DECIMAL(precision=18), table=None, primary_key=True, nullable=False)]

Это приводит к следующей ошибке:

AttributeError: Neither 'Column' object nor 'Comparator' object has an attribute 'tables'

Вы также можете заметить, что я просто пытался объявить столбцы primary_key как часть свойства dict, и в этом случае я бы отбросил весь метод __build_columns.

Есть ли у кого-нибудь совет о том, как устранить ошибку, возможно, лучший способ назначить столбцы, определенные из insp.get_indexes(), в качестве первичных ключей таблицы?

РЕДАКТИРОВАТЬ: Следует также добавить это вВ конце этого я хотел бы вызвать Base.prepare(engine), чтобы заполнить остальные или атрибуты таблицы из базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...