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.