Создание динамического класса в SQLAlchemy - PullRequest
21 голосов
/ 05 мая 2010

Нам необходимо создать классы SQLAlchemy для доступа к нескольким внешним источникам данных, число которых со временем увеличивается. Мы используем декларативную базу для наших основных моделей ORM, и я знаю, что мы можем вручную указать новые классы ORM, используя autoload = True для автоматического создания отображения.

Проблема в том, что мы должны иметь возможность генерировать их динамически, принимая что-то вроде этого:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

stored={}
stored['tablename']='my_internal_table_name'
stored['objectname']='MyObject'

и динамически превращая его в нечто подобное:

class MyObject(Base):
    __tablename__ = 'my_internal_table_name'
    __table_args__ = {'autoload':True}

Мы не хотим, чтобы классы сохранялись дольше, чем необходимо, чтобы открыть соединение, выполнить запросы, а затем закрыть соединение. Поэтому, в идеале, мы можем поместить элементы из «сохраненной» переменной выше в базу данных и извлекать их по мере необходимости. Другая проблема заключается в том, что имя объекта (например, «MyObject») может использоваться в разных соединениях, поэтому мы не можем определить его один раз и сохранить его.

Будем весьма благодарны за любые предложения о том, как это можно сделать.

Спасибо ...

1 Ответ

28 голосов
/ 05 мая 2010

Вы можете динамически создать MyObject, используя вызов с тремя аргументами type:

type(name, bases, dict)

    Return a new type object. This is essentially a dynamic form of the 
    class statement... 

Например:

mydict={'__tablename__':stored['tablename'],
        '__table_args__':{'autoload':True},}

MyObj=type(stored['objectname'],(Base,),mydict)
print(MyObj)
# <class '__main__.MyObject'>
print(MyObj.__base__)
# <class '__main__.Base'>
print(MyObj.__tablename__)
# my_internal_table_name
print(MyObj.__table_args__)
# {'autoload': True}
...