Re: [sqlalchemy] mixing association proxies and mixin classes
That works like a charm, thanks! On 06/21/2012 12:46 AM, Michael Bayer wrote: 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
[sqlalchemy] mixing association proxies and mixin classes
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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] mixing association proxies and mixin classes
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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.