【问题标题】:SQLAlchemy: getter/setter in declarative Mixin classSQLAlchemy:声明性 Mixin 类中的 getter/setter
【发布时间】:2011-04-28 16:32:23
【问题描述】:

我正在尝试为我打算在我的数据库架构中使用的 mixin 类定义简单的 getter/setter 方法:

from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import synonym, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base, declared_attr

engine = create_engine('sqlite:///')
Base = declarative_base(bind=engine)
Session = scoped_session(sessionmaker(bind=engine))


class Mixin(object):
    _attr = Column('attr', Integer)

    @property
    def attr(self):
        return self._attr

    @attr.setter
    def attr(self, value):
        self._attr = value

    attr = synonym('_attr', descriptor=attr)


class DummyClass(Base, Mixin):
    __tablename__ = 'dummy'

    id = Column(Integer, primary_key=True)

Base.metadata.create_all()

if __name__ == '__main__':
    session = Session()
    testobj = DummyClass()
    session.add(testobj)
    testobj.attr = 42
    assert testobj.attr == 42

当我尝试运行此示例时,我收到以下错误:

sqlalchemy.exc.InvalidRequestError:映射器属性(即 deferred、column_property()、relationship() 等)必须在声明性 mixin 类上声明为 @declared_attr callables。`

我的代码几乎是 SQLAlchemy Declarative Tutorial 的 1:1 副本,唯一的区别是属性/同义词是在 Mixin 类中声明的。将“@declared_attr”装饰器附加或添加到现有装饰器不会改变任何内容。

我该如何解决这种情况?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    也许将attr() 创建为@declared_attr-decorated 类方法,它返回同义词?

    class Mixin(object):
    
        _attr = Column('attr', Integer)
    
        def get_attr(self):
            return self._attr
    
        def set_attr(self, value):
             self._attr = value
    
        @declared_attr
        def attr(cls):
            return synonym('_attr', descriptor=property(cls.get_attr, cls.set_attr))
    

    【讨论】:

    • 谢谢你,成功了 :-) 如果你过分依赖语法糖并且不学习如何没有它,就会发生这种情况:3
    • 如果该列是外键则不起作用:( 具有其他列的外键的列必须声明为@declared_attr callables
    【解决方案2】:
    @contact.setter
    def contact_id(self, contact_id):
        if (contact_id is None):
            raise ValueError('contact_id can only be a uuid string')
    
        if not isinstance(contact_id, str):
            raise TypeError('contact_id is not a string')
    
        self._contact_id = contact_id
    

    使用 setter,上面的代码可以抛出更清晰的错误 比 PyAlchemy 可以扔给你的东西。

    如果可能,您也可以选择优雅地处理生产中的错误。

    【讨论】:

      猜你喜欢
      • 2011-06-22
      • 2014-06-17
      • 1970-01-01
      • 2013-07-26
      • 2018-11-14
      • 2011-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多