Создание модели с помощью отражения базы данных SQLAlchemy - PullRequest
3 голосов
/ 14 ноября 2011

В настоящее время я работаю над системой пирамид, использующей sqlalchemy.

Эта система будет включать модель (назовем ее Base), которая хранится в таблица базы данных. Эта модель должна быть расширяемой пользователем во время выполнения. В основном, пользователь должен быть в состоянии создать подкласс Base и создать новую модель (назовем ее «Child»). Дочерние элементы должны храниться в другой таблице базы данных.

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

Ответы [ 4 ]

4 голосов
/ 14 ноября 2011

Похоже, это не имеет ничего общего с «отражением базы данных», а скорее с динамическим созданием таблиц.Это довольно опасная операция, и обычно ее осуждают.

Вам следует подумать о том, как смоделировать возможную структуру, которую ваши пользователи захотят добавить в базу, и разработать свою схему на основе этого.Иногда эти гибкие структуры могут извлечь большую пользу из вертикальных таблиц, когда вы не знаете, какими могут быть столбцы.

Не забывайте, что существует целый класс систем хранения данных, которые обеспечивают более гибкую поддержку"безсхемные" модели.Что-то вроде Mongo или ZODB может иметь больше смысла.

2 голосов
/ 17 ноября 2011

Большая часть этой концепции прекрасно работает для меня, но мне не удается связать существующую таблицу с вновь созданным классом, который использует наследование нескольких таблиц. Вот некоторый код, чтобы прояснить ситуацию:

Base.metadata.reflect(bind=Session.bind)
table = Base.metadata.tables['anExistingTable']
Extension = type('Extension', (BaseClass,), {})
orm.mapper(Extension, table, inherits=orm.class_mapper(BaseClass),
    polymorphic_identity='extension')

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

ArgumentError: Class '<class 'Extension'>' 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.

Есть ли у вас идеи, почему в только что созданном классе определен основной преобразователь?

1 голос
/ 17 ноября 2011

Я только что решил проблему, описанную выше, используя следующий фрагмент кода:

table = Table('anExistingTable', Base.metadata, autoload=True, autoload_with=Session.bind)
Extension = type('Extension', (BaseClass,), {
    '__table__' : table,
    '__mapper_args__' : {
        'inherits': BaseClass,
        'polymorphic_identity': 'extension'
    }
})

Однако я не знаю, почему с первой попытки не получилось ...

1 голос
/ 17 ноября 2011

Просто определите метод генератора

def mapClass(class_name, table_name):
    # Allows to generate previously undefined mapped classes, remapping when necessary
    #For security reason this will only map a class 
    #when class is not previously declared
    #or if declared, when is a MappableClass subclass, 
    #this way we prevent to map any class.
    #Even when not able to return a mapped class it will return corresponding class_name class
    #if so, we'll get an error when accessing non existing MappableClass members
    if not globals.has_key(class_name):
        cls=type(class_name, (MappableClass,), {} )
        globals[class_name]=cls
    else:
        cls=globals[class_name]
    if issubclass(cls,MappableClass):
        tab_obj=Table(table_name,meta,autoload=True)
        mapper(cls, tab_obj)
    return cls

или унаследуйте класс генератора как здесь Я добавил метод генератора как статический в классе ответа, чтобы я мог использовать оба ранее объявленных дочерних элементаклассы или новые динамически созданные классы.

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