Thanks for the clarification. I did play around with __abstract__ but
like you said it doesn't work in the middle of the inheritance chain.
The main idea behind this approach is the DRY concept - define the
columns/relationships only once and use them interchangeably in any of
the derived STI models. This workaround sort of accomplishes that but
at the same time restricts you to a hierarchical model, whereas using
mixins is much more flexible.

On Apr 17, 4:00 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
> On Apr 17, 2012, at 6:25 PM, Amos wrote:
>
> > The problems creep in when you "mix" the mixin and the inheritance
> > functionality. The primaryjoin gotcha was the first hiccup, but now
> > I'm having trouble re-using the Mixin class on a second derived model:
>
> > ArgumentError: Column 'target_id' on class <class
> > 'uber.model.test.Manager'> conflicts with existing column
> > 'person.target_id'
>
> Well yeah, that's why the overall pattern you're doing here is a little bit 
> ill-advised.    Again this has nothing to do with the mixin, only with having 
> two separate "target_id" columns, you get the same result if you put 
> target_id on Manager and Engineer directly.
>
> What if Engineer and Manager had different notions of "target_id" ?   Should 
> declarative look at both columns, compare them and ensure they have the exact 
> same datatype and constraints, else raise an error ?  Maybe.  Though that 
> feels a little heavy handed.
>
> I know it would be nice for the ORM modeling to work in a pure way but in 
> this kind of case the realities of the relational model have to be considered 
> - which is that single table inheritance defines the table persistence in 
> terms of the base class.   You can model this as separate from Person, using 
> an intermediary class, so this is close:
>
> class PersonWithTarget(Person):
>     target_id = Column(Integer, ForeignKey('target.id'))
>     target = relationship("Target", 
> primaryjoin="PersonWithTarget.target_id==Target.id")
>
> class Engineer(PersonWithTarget):
>     pass
>
> class Manager(PersonWithTarget):
>     pass
>
> the above however is specific to single table inheritance - PersonWithTarget 
> here is mapped, but since you never use instance of it directly it doesn't 
> impact the database.   This same model wouldn't work with joined-inheritance, 
> because it would want to build a "person_with_target" table in between Person 
> and Engineer/Manager.   Ideally, PersonWithTarget should accept the 
> __abstract__ flag, meaning "don't map this class", but currently declarative 
> can't quite handle the __abstract__ class in the middle of the 
> single-inheritance scheme.
>
> Anyway there's bits of a use case here, but the workarounds are pretty 
> straightforward so I wouldn't consider this very high priority.

-- 
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