I've come up with an implementation based on concrete table
inheritance, without touching any SQLA internals like Michael
suggested. I've also added a discriminator to both base classes,
'citizen_type' and 'employee_type'. The discriminator is set via the
before_insert() method of a MapperExtension which extends the Engineer
mapper.
I realize that going this way forfeits the advantages of the
polymorphic querying, but that's ok for my application. I can still
get the same resuts, it just takes a few subqueries after I query one
of the base classes.
I've run a few tests with this setup and it seems to work - the crux
is in the engineers.join(employees).join(citizens) table definition in
the Engineer mapper and the ForeignKey constraints.
I just wanted to put this out there to see if anyone notices any
issues I am not anticipating or if this model might be helpful to
someone in the future who wants to inherit from two independent base
classes. I realize that the Engineers inheriting from Employees and
Citizens example is a bit forced, sorry about that. This is not my
actual application, I just wanted to give a simple example. Perhaps a
better application would be having 'Dragon' inheriting from both
'Bird' and 'Lizard', as given in the Agile Data essay linked to
earlier.
Here's the setup:
employees = Table('employees', metadata,
Column('employee_id', Integer, primary_key=True),
Column('employee_type', String(30), nullable=False)
)
citizens = Table('citizens', metadata,
Column('citizen_id', Integer, primary_key=True),
Column('citizen_type', String(30), nullable=False)
)
An engineer who is both an employee and a citizen would have an
employee_id and a citizen_id:
engineers = Table('engineers', metadata,
Column('id', Integer, primary_key=True)
Column('employee_id', Integer,
ForeignKey('employees.employee_id')),
Column('citizen_id', Integer, ForeignKey('citizens.citizen_id')),
Column('engineer_info', String(50)),
)
And the classes look like:
class Employee(object):
pass
class Citizen(object):
pass
class Engineer(Employe, Citizen):
pass
This is the mapper extension for setting the discriminators:
class EngineerExtension(MapperExtension):
def __init__(self):
MapperExtension.__init__(self)
def before_insert(self, mapper, connection, instance):
instance.employee_type = 'engineer'
instance.citizen_type = 'engineer'
And the mappers:
mapper(Engineer, engineers.join(employees).join(citizens),
extension=EngineerExtension())
mapper(Employee, employees)
mapper(Citizen, citizens)
Any comments on this setup are welcome!
Sam
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---