2011-09-29 2 views
1

J'essaie de créer un programme qui charge plus de 100 tables à partir d'une base de données afin que je puisse modifier toutes les apparences de l'ID utilisateur d'un utilisateur. Plutôt que de mapper toutes les tables individuellement, j'ai décidé d'utiliser une boucle pour mapper chacune des tables en utilisant un tableau d'objets. De cette façon, les définitions de table peuvent être stockées dans un fichier de configuration et mises à jour ultérieurement.SQLAlchemy: chargement dynamique de tables à partir d'une liste

Voici mon code à ce jour:

def init_model(engine): 
    """Call me before using any of the tables or classes in the model""" 
    meta.Session.configure(bind=engine) 
    meta.engine = engine 

class Table: 
    tableID = '' 
    primaryKey = '' 
    pkType = sa.types.String() 
    class mappedClass(object): 
     pass 


WIW_TBL = Table() 
LOCATIONS_TBL = Table() 

WIW_TBL.tableID = "wiw_tbl" 
WIW_TBL.primaryKey = "PORTAL_USERID" 
WIW_TBL.pkType = sa.types.String() 

LOCATIONS_TBL.tableID = "locations_tbl" 
LOCATIONS_TBL.primaryKey = "LOCATION_CODE" 
LOCATIONS_TBL.pkType = sa.types.Integer() 

tableList = ([WIW_TBL, LOCATIONS_TBL]) 

for i in tableList: 

    i.tableID = sa.Table(i.tableID.upper(), meta.metadata, 
    sa.Column(i.primaryKey, i.pkType, primary_key=True), 
    autoload=True, 
    autoload_with=engine) 

    orm.mapper(i.mappedClass, i.tableID) 

L'erreur que ce code retourne est:

sqlalchemy.exc.ArgumentError: Class '<class 'changeofname.model.mappedClass'>' 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. 

Je ne peux pas utiliser clear_mappers car il efface toutes les classes et le régime de entity_name n » t semblent s'appliquer ici.

Il semble que chaque objet veut utiliser la même classe, bien qu'ils devraient tous avoir leur propre instance.

Quelqu'un a-t-il des idées?

Répondre

1

Eh bien, dans votre cas * est le même Class vous essayez de mapper à différents Table s. Pour résoudre ce problème, créez une classe dynamique pour chaque Table:

class Table(object): 
    tableID = '' 
    primaryKey = '' 
    pkType = sa.types.String() 
    def __init__(self): 
     self.mappedClass = type('TempClass', (object,), {}) 

Mais je préférerais la version un peu plus propre:

class Table2(object): 
    def __init__(self, table_id, pk_name, pk_type): 
     self.tableID = table_id 
     self.primaryKey = pk_name 
     self.pkType = pk_type 
     self.mappedClass = type('Class_' + self.tableID, (object,), {}) 
# ... 
WIW_TBL = Table2("wiw_tbl", "PORTAL_USERID", sa.types.String()) 
LOCATIONS_TBL = Table2("locations_tbl", "LOCATION_CODE", sa.types.Integer()) 
+0

parfait, c'est exactement ce que je avais besoin! J'avais déjà essayé type() plus tôt mais sans succès. Merci pour cela, très apprécié! Bien que, pour une raison quelconque, il ne passe pas à la vue, mais je l'ai compris: D – JackalopeZero

+0

Pour que les classes soient visibles à l'importation, vous devez les ajouter à 'globals()'. Par exemple: après le 'self.mappedClass = type ('Class_' + self.tableID, (objet,), {})' line add 'globals() ['Class_' + self.tableID] = ligne self.mappedClass' . Dans ce cas, la vue pourra importer la classe 'Class_locations_tbl' et' Class_wiw_tbl' – van

Questions connexes