do it like this for now:

class FilterMixin(object):
    @declared_attr
    def _filters(cls):
        cls.filters = association_proxy('_filters', 'filter')
        return relationship(cls.filter_class,
               cascade='all,delete,delete-orphan')


there's a patch for 0.8 only in http://www.sqlalchemy.org/trac/ticket/2517 .



On Jun 20, 2012, at 1:13 PM, Wichert Akkerman wrote:

> I am struggling a little bit with mixin classes. The pattern I am trying to 
> implement is a mixin-class that adds a list of validated search queries to a 
> model. A minimised version of the code is below. The problem I am running 
> into is that putting an association_proxy on a mixin class does not appear to 
> work here: it always picks the first seen class type to create new values 
> instead of picking up what the relationship of the current instance requires. 
> With the example below that results in this error:
> 
> AssertionError: Attribute '_filters' on class '<class '__main__.TypeB'>' 
> doesn't handle objects of type'<class '__main__.FilterA'>'
> 
> 
> 
> My initial though was that this might be fixed by making the 
> association_proxy instance itself a declared_attr, but that results in other 
> problems.
> 
> Is there an alternative way to implement this, or is this a bug in the 
> declarative logic?
> 
> 
> from sqlalchemy import *
> from sqlalchemy.orm import *
> from sqlalchemy.ext.associationproxy import association_proxy
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.ext.declarative import declared_attr
> 
> 
> metadata = MetaData()
> BaseObject = declarative_base(metadata=metadata)
> 
> class BaseFilter(BaseObject):
>    __abstract__ = True
> 
>    id = Column(Integer(), primary_key=True, autoincrement=True)
>    filter = Column(UnicodeText(), nullable=False)
> 
>    @declared_attr
>    def __tablename__(cls):
>        return '%s_filter' % cls.parent_tablename
> 
>    @declared_attr
>    def parent_id(cls):
>        return Column(Integer(),
>            ForeignKey('%s.id' % cls.parent_tablename,
>                ondelete='CASCADE', onupdate='CASCADE'),
>            nullable=False, index=True)
> 
>    def __init__(self, filter, **kw):
>        super(BaseFilter, self).__init__(filter=filter, **kw)
> 
>    @validates('filter')
>    def validate_filter(self, key, value):
>        assert len(value)>  2
>        return value
> 
> 
> class FilterA(BaseFilter):
>    parent_tablename = 'type_a'
> 
> 
> class FilterB(BaseFilter):
>    parent_tablename = 'type_b'
> 
> 
> class FilterMixin(object):
>    @declared_attr
>    def _filters(cls):
>        return relationship(cls.filter_class,
>                cascade='all,delete,delete-orphan')
> 
>    filters = association_proxy('_filters', 'filter')
> 
> #    @declared_attr
> #    def filters(cls):
> #        return association_proxy('_filters', 'filter')
> 
> 
> class TypeA(BaseObject, FilterMixin):
>    __tablename__ = 'type_a'
>    filter_class = FilterA
>    id = Column(Integer(), primary_key=True, autoincrement=True)
> 
> class TypeB(BaseObject, FilterMixin):
>    __tablename__ = 'type_b'
>    filter_class = FilterB
>    id = Column(Integer(), primary_key=True, autoincrement=True)
> 
> 
> engine = create_engine('sqlite://')
> metadata.bind = engine
> metadata.create_all()
> Session = sessionmaker(bind=engine)
> session = Session()
> 
> session.add(TypeA(filters=[u'foo']))
> session.add(TypeB(filters=[u'foo']))
> session.flush()
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to