首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于在SQLAlchemy中创建混合属性的自定义元类

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

Stack Overflow用户
提问于 2012-12-29 09:58:54
回答 1查看 684关注 0票数 2

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

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

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

代码语言:javascript
复制
class SpecialColumn(object):
     pass

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

代码语言:javascript
复制
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实例,并让用户用新的基定义类:

代码语言:javascript
复制
MyBase = declarative_base(metaclass=MyDeclarativeMeta)

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

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

代码语言:javascript
复制
def setter(self, (v1, v2)):
    setattr(self, col1_name, v1)
    setattr(self, col2_name, v2)

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-12-31 08:14:25

不需要为SQLAlchemy映射的类使用元类,因为我们提供了大量的events来在创建和/或映射时向类添加功能。mapper_configured在这里可能很好用,如果你在0.8上,你可以直接应用于MyBase

代码语言:javascript
复制
@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()是这里的最佳方法,简单且切中要害。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14078052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档