well it will "work" if you say this: class PolymorphicMixin(object): discriminator = Column('discriminator', types.String(50)) @declared_attr def __mapper_args__(cls): ret = {'polymorphic_identity': cls.__name__} if Base in cls.__bases__: ret['polymorphic_on'] = cls.discriminator return ret
This because, when declarative sees a plain Column on a mixin, it makes a copy of it for the target class, then takes the step of placing that column into the __mapper_args__ dictionary as a replacement for all occurrences of the original column. This is one of the several tricks declarative uses to get mixins to work (I was opposed to mixins for a long time for the reason of these tricks being necessary). When using a function to generate Column, it gets called once by declarative, once by __mapper_args__(), we then have two Column objects that are totally different. In 0.7 an error message is raised for this condition, I'd imagine you tried 0.6 and it silently failed. However, this approach of "discriminator = Column" at the class level doesn't totally really "work", since you'll see that it puts a "discriminator" column on all the subclasses too. It sort of works out and gets populated on the sub-table and all that but we don't really want that. So we'll instead take advantage of memoizing on the class itself, replacing the declared_attr with the column itself, and then it all works: class PolymorphicMixin(object): @declared_attr def discriminator(cls): if 'discriminator' in cls.__dict__: return cls.discriminiator else: cls.discriminator = d = Column('discriminator', types.String(50)) return d @declared_attr def __mapper_args__(cls): ret = {'polymorphic_identity': cls.__name__} if Base in cls.__bases__: ret['polymorphic_on'] = cls.discriminator return ret On Jan 26, 2011, at 8:30 PM, scott wrote: > Is it possible to make a generalized declarative mixin class that > abstracts away all of the syntax of inheritance? I've seen examples > that set up the __mapper_args__ but not the discriminator column, and > examples that set up the discriminator column but not the > __mapper_args__, but none with both. > > This is roughly how I imagine it should work, but when I tried this, > rows were created with null values for the discriminator. A full > example is here: > https://gist.github.com/797893 > > class PolymorphicMixin(object): > @declared_attr > def discriminator(cls): > if Base in cls.__bases__: > return Column('discriminator', types.String(50)) > for b in cls.__bases__: > if hasattr(b, 'discriminator'): > return b.discriminator > > @declared_attr > def __mapper_args__(cls): > ret = {'polymorphic_identity': cls.__name__} > if Base in cls.__bases__: > ret['polymorphic_on'] = PolymorphicMixin.discriminator > return ret > > Thanks, > Scott > > -- > 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.