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.

Reply via email to