2011-11-14 23 views
3

現在、sqlalchemyを使用するピラミッドシステムで作業しています。SQLAlchemyデータベースリフレクションによるモデル作成

このシステムには、 データベーステーブルに格納されているモデル(Baseと呼ぶ)が含まれます。このモデルは、実行時にユーザーが拡張する必要があります。基本的に、ユーザ はベースをサブクラス化し、新しいモデルを作成できます(これを「子」と呼ぶ)。 子は別のデータベーステーブルに格納する必要があります。

利用可能なすべての例は、定義済みのモデルでデータベースリフレクションを処理するようです。 データベースリフレクションを使用して完全なモデルクラスを生成する最善の方法は何でしょうか?

答えて

1

私は、次のコードスニペットを使用することにより、上記の問題を解決した:

table = Table('anExistingTable', Base.metadata, autoload=True, autoload_with=Session.bind) 
Extension = type('Extension', (BaseClass,), { 
    '__table__' : table, 
    '__mapper_args__' : { 
     'inherits': BaseClass, 
     'polymorphic_identity': 'extension' 
    } 
}) 

最初の試みがうまくいかなかった理由しかし、私にはわからない...

4

これは、「データベースリフレクション」とはあまり関係ありませんが、ダイナミックなテーブル作成とは関係ありません。これはかなり危険な操作であり、一般的には眉をひそめます。

ユーザーがベースに追加する可能性のある構造をモデル化する方法を考えて、その周りにスキーマを設計する必要があります。場合によっては、列が何であるかわからないときに、これらの柔軟な構造が垂直テーブルから多くの利益を得ることがあります。

「スキーマレス」モデルの柔軟性の高いサポートを提供するデータストレージシステムのクラス全体が存在することを忘れないでください。モンゴやZODBのようなものがここでもっと意味をなさないかもしれません。

2

このコンセプトのほとんどは私のためにうまく動作しますが、既存のテーブルを複数テーブルの継承を使用する新しく作成されたクラスにバインドできません。ここで物事をより明確にするいくつかのコードは次のとおりです。

Base.metadata.reflect(bind=Session.bind) 
table = Base.metadata.tables['anExistingTable'] 
Extension = type('Extension', (BaseClass,), {}) 
orm.mapper(Extension, table, inherits=orm.class_mapper(BaseClass), 
    polymorphic_identity='extension') 

これは、次のエラーが発生:ちょうどされているクラスに定義された主マッパーがある理由

ArgumentError: Class '<class 'Extension'>' 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. 

あなたが任意のアイデアを持っていますか作成した?

1

ちょうど私が答えのクラスにstaticとして発電方法を追加しましたので、私は両方の前に宣言子クラスまたは新しいdinamically-作成を使用することができる発電方法

def mapClass(class_name, table_name): 
    # Allows to generate previously undefined mapped classes, remapping when necessary 
    #For security reason this will only map a class 
    #when class is not previously declared 
    #or if declared, when is a MappableClass subclass, 
    #this way we prevent to map any class. 
    #Even when not able to return a mapped class it will return corresponding class_name class 
    #if so, we'll get an error when accessing non existing MappableClass members 
    if not globals.has_key(class_name): 
     cls=type(class_name, (MappableClass,), {}) 
     globals[class_name]=cls 
    else: 
     cls=globals[class_name] 
    if issubclass(cls,MappableClass): 
     tab_obj=Table(table_name,meta,autoload=True) 
     mapper(cls, tab_obj) 
    return cls 

またはhere としてジェネレータクラスを継承を定義、1つ。

+0

ねえ、おかげで答えのために。しかし、あなたはマルチテーブル継承のコンセプトを得る方法を知っていますか(下記参照)? – fynn

+0

まあ... sqlalchemyがどのようにテーブルの継承を処理するのか分かりません...データベースに継承情報を格納していますか? (答える代わりに申し訳ありません)もしそうでなければ、あなたはそれを保存し、それをクラス生成で取り戻す必要があります。とにかく、継承マッパー引数をmapClassメソッドに追加できます – Kelbethor

+0

はい、多型はデータベースに保存されています([こちらを参照](http://www.sqlalchemy.org/docs/orm/inheritance.html#joined-table-継承))。しかし、私は、データベースの反映と継承の組み合わせに対する解決策を見つけるのに苦労しています。 – fynn

関連する問題