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.