Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy: getter/setter in declarative Mixin class

I am trying to define simple getter/setter methods for a mixin class that I intend to use in my database schema:

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

When I try to run this example, I get the following error:

sqlalchemy.exc.InvalidRequestError: Mapper properties (i.e. deferred,column_property(), relationship(), etc.) must be declared as @declared_attr callables on declarative mixin classes.`

My code is almost a 1:1 copy from the SQLAlchemy Declarative Tutorial, with the only difference that the property/synonym is declared in a Mixin class. Appending or prepending the "@declared_attr" decorator to the existing decorators does not change anything.

How do I resolve this situation?

like image 203
jbaiter Avatar asked Apr 28 '11 16:04

jbaiter


1 Answers

Perhaps create the attr() as an @declared_attr-decorated class method which returns the synonym?

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))
like image 192
samplebias Avatar answered Nov 18 '22 23:11

samplebias