SQLAlchemy の上にカスタム インターフェイスを作成して、事前定義されたハイブリッド プロパティが透過的にサポートされるようにしたいと考えています。
具体的には、クラスSpecialColumn
とメタクラスを作成して、ユーザーがSpecialColumn
クラスの属性として追加したときに、カスタム メタクラスがその属性を 2 つの SQLAlchemy に置き換え、Column
これら 2 つの列をタプルとして取得および設定するハイブリッド プロパティを追加したいと考えています。これまでの私のアプローチは次のとおりです。
まず、特別な列タイプを定義しました。
class SpecialColumn(object):
pass
次に、 DeclarativeMeta から継承するメタクラスを定義しました。これは、クラスをスキャンして のインスタンスを探し、それらを 2 つの とハイブリッド プロパティ (クロージャとして定義)SpecialColumn
に置き換えます。Column
class MyDeclarativeMeta(DeclarativeMeta):
def __new__(cls, name, bases, attrs):
for name, col in attrs.items():
if isinstance(col, SpecialColumn):
# Replacing the column
del attrs[name]
col1_name = '_{0}_1'.format(name)
col2_name = '_{0}_2'.format(name)
attrs[col1_name] = Column(...)
attrs[col2_name] = Column(...)
# Adding the hybrid property
def getter(self):
return (getattr(self, col1_name), getattr(self, col2_name))
attrs[name] = hybrid_property(getter)
最後にdeclarative_base
、それを使用して のインスタンスを作成し、ユーザーが新しいベースでクラスを定義できるようにします。
MyBase = declarative_base(metaclass=MyDeclarativeMeta)
class MyClass(MyBase):
col1 = SpecialColumn()
col2 = Column(...)
私の質問のために:まず、私のアプローチは正しいですか?次に、メタクラスを使用してセッターを追加するにはどうすればよいですか? 次のようにするのは正しいでしょうか:
def setter(self, (v1, v2)):
setattr(self, col1_name, v1)
setattr(self, col2_name, v2)
そして、単に行うattrs[name].setter(setter)
?