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.