2010-05-04 12 views
19

Mamy potrzebę tworzenia klas SQLAlchemy, aby uzyskać dostęp do wielu zewnętrznych źródeł danych, które z czasem będą wzrastać. Używamy deklaratywnej podstawy dla naszych podstawowych modeli ORM i wiem, że możemy ręcznie określić nowe klasy ORM przy użyciu autoload = True, aby automatycznie generować mapowanie.Tworzenie klas dynamicznych w SQLAlchemy

Problemem jest to, że musimy być w stanie wygenerować je dynamicznie bierze coś takiego:

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

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

i zamieniając go w coś tak dynamicznie:

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

My nie chcemy klasy utrzymują się dłużej niż to konieczne do otwarcia połączenia, wykonania zapytań, a następnie zamknięcia połączenia. W związku z tym najlepiej byłoby umieścić elementy w powyższej zmiennej "zapisanej" w bazie danych i wyciągnąć je w razie potrzeby. Innym wyzwaniem jest to, że nazwa obiektu (np. "MyObject") może być używana na różnych połączeniach, więc nie możemy zdefiniować go raz i zachować go.

Wszelkie sugestie dotyczące tego, jak można to osiągnąć, byłyby bardzo mile widziane.

Dzięki ...

Odpowiedz

24

można dynamicznie tworzyć MyObject pomocą 3-argument call to type:

type(name, bases, dict) 

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

Na przykład:

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

chłopiec ... czuję się głupi. Takie proste rozwiązanie. Nie wiedziałem, że metoda typu jest tak potężna. Zmodyfikowałem nieznacznie rozwiązanie, aby umieścić nazwę obiektu w przestrzeni globalnej, aby mogło zostać uwzględnione bezpośrednio w zapytaniach SQLAlchemy: globals() [stored ['objectname']] = type (stored ['objectname'], (Base,), mydict) Dzięki ... świetne rozwiązanie. – PlaidFan

+3

Nie czuj się głupio! Nauczyłem się tej sztuczki, obserwując, jak inni używają jej tutaj na SO. Teraz też znasz tę sztuczkę i możesz zadziwić swoich przyjaciół. :) – unutbu

Powiązane problemy