2

宣言ベースを使用して、SQLAlchemy でバックエンド アプリケーションを作成しています。ORM には約 15 個のテーブルが必要で、それぞれが SQLAlchemy のクラス オブジェクトにマップされます。これらのクラス オブジェクトはすべて同じように定義されているため、ファクトリ パターンを使用するとクラスをより簡潔に生成できると考えました。ただし、これらのクラスを定義するだけでなく、プロジェクト全体でインポートして使用できるように、一意の変数名に割り当てる必要があります。

(この質問が少し長い場合は申し訳ありませんが、問題をよりよく理解したので更新しました。)

非常に多くの列 (~1000) があるため、読みやすいように外部テキスト ファイルで名前と型を定義します。モデルを宣言する方法の 1 つを実行すると、次のようになります。

class Foo1(Base):
    __tablename___ = 'foo1'

class Foo2(Base):
    __tablename___ = 'foo2'

... etc

次に、外部テキスト ファイルの内容をループし、setattr()各クラス定義で を使用して、列を追加できます。

これは問題ありませんが、約 15 のテーブルがあるため、繰り返しが多すぎるように感じます。その代わりに、クラスを動的に定義できるファクトリ関数を作成することに挑戦しました。

def orm_factory(class_name):
    class NewClass(Base):
        __tablename__ = class_name.lower()
    NewClass.__name__ = class_name.upper()
    return NewClass

ここでも、列をループして を使用できますsetattr()。まとめてみるとこんな感じ。

for class_name in class_name_list:
    ORMClass = orm_factory(class_name)
    header_keyword_list = get_header_keyword_list(class_name)
    define_columns(ORMClass, header_keyword_list)

Whereget_header_keyword_listは列情報を取得し、代入をdefine_columns実行します。setattr()これを使用して実行するとBase.metadata.create_all()、SQL スキーマが正常に生成されます。

しかし、これらのクラス定義を別のモデルにインポートしようとすると、次のようなエラーが発生します。

SAWarning: The classname 'NewClass' is already in the registry of this declarative base, mapped to <class 'ql_database_interface.IR_FLT_0'>

これは、昨日学んだことに基づいて完全に理にかなっていることがわかりました: Python クラス変数名 vs __name__

ファクトリ関数でクラスジェネレーターとして使用することでこれに対処できますtype(以下の2つの回答がそうです)。ただし、クラスがファクトリ関数で動的に構築されている間、その関数の出力が割り当てられる変数は静的であるため、これはクラスをインポートできるという問題を解決しません。辞書キーなどの動的なものであっても、別のモジュールからインポートするには、モジュールの名前空間に存在する必要があります。詳細については、私の回答を参照してください。

4

2 に答える 2

2

これは大ざっぱなアイデアのように聞こえます。しかし、解決するのは楽しいので、それを機能させる方法を次に示します。

私が理解しているように、あなたの問題は、動的に作成されたクラスをモジュールに追加したいということです。モジュールとinit .py ファイルを使用してハックを作成しました。

dynamicModule/__init__.py:

import dynamic

class_names = ["One", "Two", "Three"]

for new_name in class_names:
     dynamic.__dict__['Class%s' % new_name] = type("Class%s" % (new_name), (object,), {'attribute_one': 'blah'})

dynamicModule/dynamic.py:

"""Empty file"""

test.py:

import dynamicModule
from dynamicModule import dynamic
from dynamicModule.dynamic import ClassOne

dynamic.ClassOne
"""This all seems evil but it works for me on python 2.6.5"""

__init__.py:

"""Empty file"""
于 2013-08-22T01:47:39.350 に答える