views:

121

answers:

1

We have a need to create SQLAlchemy classes to access multiple external data sources that will increase in number over time. We use the declarative base for our core ORM models and I know we can manually specify new ORM classes using the autoload=True to auto generate the mapping.

The problem is that we need to be able generate them dynamically taking something like this:

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

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

and turning it into something like this dynamically:

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

We don't want the classes to persist longer than necessary to open a connection, perform the queries, and then closing the connection. Therefore, ideally, we can put the items in the "stored" variable above into a database and pull them as needed. The other challenge is that the object name (e.g. "MyObject") may be used on different connections so we cannot define it once and keep it around.

Any suggestions on how this might be accomplished would be greatly appreciated.

Thanks...

+3  A: 

You can dynamically create MyObject using the 3-argument call to type:

type(name, bases, dict)

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

For example:

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}
unutbu
boy...i feel dumb. Such a simple solution. I didn't realize the type method was so powerful.I modified the solution slightly to put the object name in the global space so it could be included in SQLAlchemy queries directly:globals()[stored['objectname']]=type(stored['objectname'],(Base,),mydict)Thanks...great solution.
PlaidFan
Don't feel dumb! I learned this trick by watching others use it here on SO. Now you know the trick too and can wow your friends. :)
unutbu