在SQLAlchemy中创建混合属性的自定义元类

2024-04-25 10:13:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在SQLAlchemy之上创建一个自定义接口,以便透明地支持一些预定义的混合属性。在

具体地说,我想创建一个类SpecialColumn和一个元类,这样当用户添加{}作为类的属性时,我的自定义元类将该属性替换为两个SQLAlchemy Column,并添加一个混合属性,该属性获取并设置这两个列作为元组。 到目前为止,我的方法是:

首先,我定义了我的特殊列类型:

class SpecialColumn(object):
     pass

然后,我定义了一个继承自DeclarativeMeta的元类,它扫描类中的SpecialColumn实例,并用两个{}和一个混合属性(定义为闭包)替换它们:

^{pr2}$

最后,我用它构造了一个declarative_base的实例,让用户用新的基定义类:

MyBase = declarative_base(metaclass=MyDeclarativeMeta)

class MyClass(MyBase):
    col1 = SpecialColumn()
    col2 = Column(...)

现在回答我的问题: 首先,我的方法正确吗? 其次,如何使用元类添加setter?正确的做法是:

def setter(self, (v1, v2)):
    setattr(self, col1_name, v1)
    setattr(self, col2_name, v2)

然后简单地做attrs[name].setter(setter)?在


Tags: 实例方法用户nameselfbase属性定义
1条回答
网友
1楼 · 发布于 2024-04-25 10:13:57

没有必要为SQLAlchemy映射类使用元类,因为我们提供了大量的events来在类创建和/或映射时向类添加特性。mapper_configured在这里可能很好,如果您使用0.8,则可以直接向MyBase申请:

@event.listens_for(MyBase, 'mapper_configured')
def get_special_columns(mapper, cls):
    for attrname in dir(cls):
        val = getattr(cls, attrname)
        if isinstance(val, SpecialColumn):
             name1, name2 = "_%s_1" % attrname, "_%s_2" % attrname
             setattr(cls, name1, Column(...))
             setattr(cls, name2, Column(...))

             @hybrid_property
             def myhybrid(self):
                 return getattr(self, name1), getattr(self, name2)

             @myhybrid.setter
             def myhybrid(self, value):
                 setattr(self, name1, value[0])
                 setattr(self, name2, value[1])

             setattr(cls, attrname, myhybrid)

请注意,setattr()是实现此目的的最佳方法,简单明了。在

相关问题 更多 >