diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-03-24 06:28:27 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-03-24 06:28:27 +0000 |
| commit | b1deaf1fb76e2ed60da4bea5e1b5cc2b732b8a23 (patch) | |
| tree | e2d02b4b610a4768c38749675f094fce6b444783 /examples/polymorph | |
| parent | cd39a0a78049f0e1978bc7990d7c677dbb891ac4 (diff) | |
| download | sqlalchemy-b1deaf1fb76e2ed60da4bea5e1b5cc2b732b8a23.tar.gz | |
some more tweaks to get more advanced polymorphic stuff to work
Diffstat (limited to 'examples/polymorph')
| -rw-r--r-- | examples/polymorph/polymorph.py | 16 | ||||
| -rw-r--r-- | examples/polymorph/polymorph2.py | 137 |
2 files changed, 146 insertions, 7 deletions
diff --git a/examples/polymorph/polymorph.py b/examples/polymorph/polymorph.py index 804ef4e7a..d105a64ea 100644 --- a/examples/polymorph/polymorph.py +++ b/examples/polymorph/polymorph.py @@ -23,7 +23,7 @@ people = Table('people', db, engineers = Table('engineers', db, Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), - Column('description', String(50))).create() + Column('special_description', String(50))).create() managers = Table('managers', db, Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), @@ -36,7 +36,7 @@ class Person(object): return "Ordinary person %s" % self.name class Engineer(Person): def __repr__(self): - return "Engineer %s, description %s" % (self.name, self.description) + return "Engineer %s, description %s" % (self.name, self.special_description) class Manager(Person): def __repr__(self): return "Manager %s, description %s" % (self.name, self.description) @@ -69,7 +69,7 @@ person_join = select( [people, managers.c.description,column("'manager'").label('type')], people.c.person_id==managers.c.person_id).union_all( select( - [people, engineers.c.description, column("'engineer'").label('type')], + [people, engineers.c.special_description.label('description'), column("'engineer'").label('type')], people.c.person_id==engineers.c.person_id)).alias('pjoin') @@ -83,7 +83,9 @@ print "Person selectable:", str(person_join.select(use_labels=True)), "\n" class PersonLoader(MapperExtension): def create_instance(self, mapper, row, imap, class_): if row['pjoin_type'] =='engineer': - return Engineer() + e = Engineer() + e.special_description = row['pjoin_description'] + return e elif row['pjoin_type'] =='manager': return Manager() else: @@ -111,8 +113,8 @@ assign_mapper(Company, companies, properties={ c = Company(name='company1') c.employees.append(Manager(name='pointy haired boss', description='manager1')) -c.employees.append(Engineer(name='dilbert', description='engineer1')) -c.employees.append(Engineer(name='wally', description='engineer2')) +c.employees.append(Engineer(name='dilbert', special_description='engineer1')) +c.employees.append(Engineer(name='wally', special_description='engineer2')) c.employees.append(Manager(name='jsmith', description='manager2')) objectstore.commit() @@ -125,7 +127,7 @@ for e in c.employees: print "\n" dilbert = Engineer.mapper.get_by(name='dilbert') -dilbert.description = 'hes dibert!' +dilbert.special_description = 'hes dibert!' objectstore.commit() objectstore.clear() diff --git a/examples/polymorph/polymorph2.py b/examples/polymorph/polymorph2.py new file mode 100644 index 000000000..99ee6c34c --- /dev/null +++ b/examples/polymorph/polymorph2.py @@ -0,0 +1,137 @@ +from sqlalchemy import * +import sys + +# this example illustrates a polymorphic load of two classes, where each class has a very +# different set of properties + +db = create_engine('sqlite://', echo=True, echo_uow=False) + +# a table to store companies +companies = Table('companies', db, + Column('company_id', Integer, primary_key=True), + Column('name', String(50))).create() + +# we will define an inheritance relationship between the table "people" and "engineers", +# and a second inheritance relationship between the table "people" and "managers" +people = Table('people', db, + Column('person_id', Integer, primary_key=True), + Column('company_id', Integer, ForeignKey('companies.company_id')), + Column('name', String(50))).create() + +engineers = Table('engineers', db, + Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), + Column('status', String(30)), + Column('engineer_name', String(50)), + Column('primary_language', String(50)), + ).create() + +managers = Table('managers', db, + Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), + Column('status', String(30)), + Column('manager_name', String(50)) + ).create() + + +# create our classes. The Engineer and Manager classes extend from Person. +class Person(object): + def __repr__(self): + return "Ordinary person %s" % self.name +class Engineer(Person): + def __repr__(self): + return "Engineer %s, status %s, engineer_name %s, primary_language %s" % (self.name, self.status, self.engineer_name, self.primary_language) +class Manager(Person): + def __repr__(self): + return "Manager %s, status %s, manager_name %s" % (self.name, self.status, self.manager_name) +class Company(object): + def __repr__(self): + return "Company %s" % self.name + +# assign plain vanilla mappers +assign_mapper(Person, people) +assign_mapper(Engineer, engineers, inherits=Person.mapper) +assign_mapper(Manager, managers, inherits=Person.mapper) + +# create a union that represents both types of joins. we have to use +# nulls to pad out the disparate columns. +person_join = select( + [ + people, + managers.c.status, + managers.c.manager_name, + null().label('engineer_name'), + null().label('primary_language'), + column("'manager'").label('type') + ], + people.c.person_id==managers.c.person_id).union_all( + select( + [ + people, + engineers.c.status, + null().label('').label('manager_name'), + engineers.c.engineer_name, + engineers.c.primary_language, + column("'engineer'").label('type') + ], + people.c.person_id==engineers.c.person_id)).alias('pjoin') + + +# MapperExtension object. +class PersonLoader(MapperExtension): + def create_instance(self, mapper, row, imap, class_): + if row[person_join.c.type] =='engineer': + return Engineer() + elif row[person_join.c.type] =='manager': + return Manager() + else: + return Person() + + def populate_instance(self, mapper, instance, row, identitykey, imap, isnew): + if row[person_join.c.type] =='engineer': + Engineer.mapper.populate_instance(instance, row, identitykey, imap, isnew) + return False + elif row[person_join.c.type] =='manager': + Manager.mapper.populate_instance(instance, row, identitykey, imap, isnew) + return False + else: + return True + + + +people_mapper = mapper(Person, person_join, extension=PersonLoader()) + +assign_mapper(Company, companies, properties={ + 'employees': relation(people_mapper, lazy=False, private=True) +}) + +c = Company(name='company1') +c.employees.append(Manager(name='pointy haired boss', status='AAB', manager_name='manager1')) +c.employees.append(Engineer(name='dilbert', status='BBA', engineer_name='engineer1', primary_language='java')) +c.employees.append(Engineer(name='wally', status='CGG', engineer_name='engineer2', primary_language='python')) +c.employees.append(Manager(name='jsmith', status='ABA', manager_name='manager2')) +objectstore.commit() + +objectstore.clear() + +c = Company.get(1) +for e in c.employees: + print e, e._instance_key + +print "\n" + +dilbert = Engineer.mapper.get_by(name='dilbert') +dilbert.engineer_name = 'hes dibert!' +objectstore.commit() + +objectstore.clear() +c = Company.get(1) +for e in c.employees: + print e, e._instance_key + +objectstore.delete(c) +objectstore.commit() + + +managers.drop() +engineers.drop() +people.drop() +companies.drop() |
