2010-05-04 20 views
19

Tenemos la necesidad de crear clases SQLAlchemy para acceder a múltiples fuentes de datos externas que aumentarán en número a lo largo del tiempo. Utilizamos la base declarativa para nuestros modelos principales de ORM y sé que podemos especificar manualmente nuevas clases de ORM utilizando la carga automática = True para generar automáticamente la asignación.Creación dinámica de clases en SQLAlchemy

El problema es que tenemos que ser capaces de generarlos dinámicamente tomando algo como esto:

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

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

y convertirlo en algo como esto de forma dinámica:

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

No queremos que la las clases persisten más de lo necesario para abrir una conexión, realizar consultas y luego cerrar la conexión. Por lo tanto, idealmente, podemos colocar los elementos en la variable "almacenada" arriba en una base de datos y extraerlos según sea necesario. El otro desafío es que el nombre del objeto (por ejemplo, "MyObject") se puede usar en diferentes conexiones, por lo que no podemos definirlo una sola vez y mantenerlo.

Cualquier sugerencia sobre cómo se podría lograr esto sería muy apreciada.

Gracias ...

Respuesta

24

Puede crear dinámicamente MyObject utilizando el 3-argument call to type:

type(name, bases, dict) 

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

Por ejemplo:

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} 
+0

chico ... Me siento tonta. Una solución tan simple. No me di cuenta de que el método de tipo era tan poderoso. Modifiqué la solución ligeramente para poner el nombre del objeto en el espacio global para que se pudiera incluir en las consultas de SQLAlchemy directamente: globals() [stored ['objectname']] = type (stored ['objectname']], (Base,), mydict) Gracias ... gran solución. – PlaidFan

+3

¡No se sienta tonto! Aprendí este truco al ver a otros usarlo aquí en SO. Ahora conoces el truco también y puedes sorprender a tus amigos. :) – unutbu

Cuestiones relacionadas