2010-05-04 18 views
19

Nous avons besoin de créer des classes SQLAlchemy pour accéder à plusieurs sources de données externes dont le nombre augmentera avec le temps. Nous utilisons la base déclarative pour nos modèles ORM de base et je sais que nous pouvons spécifier manuellement de nouvelles classes ORM en utilisant le paramètre autoload = True pour générer automatiquement le mappage.Création de classes dynamiques dans SQLAlchemy

Le problème est que nous devons être en mesure de prendre les générer dynamiquement quelque chose comme ceci:

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

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

et le transformer en quelque chose comme ceci dynamique:

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

Nous ne voulons pas que Les classes doivent rester plus longtemps que nécessaire pour ouvrir une connexion, exécuter les requêtes et fermer la connexion. Par conséquent, idéalement, nous pouvons placer les éléments de la variable "stockée" ci-dessus dans une base de données et les récupérer au besoin. L'autre défi est que le nom de l'objet (par exemple "MyObject") peut être utilisé sur différentes connexions, de sorte que nous ne pouvons pas le définir une fois et le conserver.

Toute suggestion sur la façon dont cela pourrait être accompli serait grandement appréciée.

Merci ...

Répondre

24

Vous pouvez créer dynamiquement MyObject en utilisant le 3-argument call to type:

type(name, bases, dict) 

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

Par exemple:

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

garçon ... je me sens stupide. Une solution aussi simple. Je n'ai pas réalisé que la méthode de type était si puissante. J'ai légèrement modifié la solution pour placer le nom de l'objet dans l'espace global afin qu'il puisse être inclus directement dans les requêtes SQLAlchemy: globals() [stored ['objectname']] = type (stored ['objectname'], (Base,), mydict) Merci ... excellente solution. – PlaidFan

+3

Ne vous sentez pas stupide! J'ai appris cette astuce en regardant les autres l'utiliser ici sur SO. Maintenant vous connaissez le tour aussi et pouvez impressionner vos amis. :) – unutbu