This is probably violating some normal form, but after playing with it (Thanks Michael and Jonathan), this seems to work for what I'm using. Suggestions welcome on improving it.
#!/usr/bin/env python from sqlalchemy import Column, ForeignKey, Integer, MetaData, Sequence, String, \ create_engine from sqlalchemy.orm import backref, joinedload, relationship, \ scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base, declared_attr from sqlalchemy.pool import NullPool engine = create_engine(u"sqlite:///./test.sql", poolclass=NullPool) metadata = MetaData(bind=engine) session = scoped_session(sessionmaker(autoflush=True, autocommit=False, bind=engine) ) Base = declarative_base(metadata=metadata) # Table base class to assign table name based on class name and # add id column class CommonBase(object): @declared_attr def __tablename__(cls): return cls.__name__.lower() id = Column(Integer, primary_key=True) # Table class to keep track of manufacturers class Manufacturer(CommonBase, Base): def __repr__(self): return "<Manufacturer(name='%s')>" % self.name name = Column(String(30)) models = relationship("Model", order_by="Model.id", backref="manufacturer", cascade="all, delete-orphan", primaryjoin="Manufacturer.id==Model.manufacturer_id", lazy='joined') # table class to keep track of models related to Manufacturer. class Model(CommonBase, Base): def __repr__(self): return "<Model(name=%s')>" % self.name manufacturer_id = Column(Integer, ForeignKey("manufacturer.id")) name = Column(String(20)) sources = relationship("Source", order_by="Source.id", backref="model", cascade="all, delete-orphan", primaryjoin="Model.id==Source.model_id", lazy='joined') # Table class to keep track of sources related to Model. class Source(CommonBase, Base): def __repr__(self): return "<Source(pjlink_name='%s', pjlink_code='%s', text='%s')>" % \ (self.pjlink_name, self.pjlink_code, self.text) model_id = Column(Integer, ForeignKey('model.id')) pjlink_name = Column(String(15)) pjlink_code = Column(String(2)) text = Column(String(30)) # Table class to keep track of installed projectors. # Use a separate query to get manufacturer/model/sources rather than # using a relationship (one-time at program start so minimal impact). class Installed(CommonBase, Base): name = Column(String(20)) location = Column(String(30)) ip = Column(String(50)) # Class for projector instances. class Projector(object): def __init__(name=None, location=None, ip=None): self.name = name self.location = location self.ip = ip # Following variables will be filled-in after projector connected. self.make = None self.model = None # Following variable will be filled in after projector connected and db queried. # List of pjlink dictionary items: [ {name='', code='', text=''}, ...] self.sources = None metadata.create_all() m = Manufacturer(name='eiki') m.models = [ Model(name='lc/xl200') ] m.models[0].sources = [ Source(pjlink_name='RGB1', pjlink_code='11', text='HDMI RGB'), Source(pjlink_name='RGB2', pjlink_code='12', text='VGA RGB') ] session.add(m) session.commit() p = session.query(Manufacturer, Model).\ options(joinedload(Manufacturer.models), joinedload(Model.sources)).\ filter(Manufacturer.name=='eiki', Model.name=='lc/xl200').\ all() if len(p) == 0: m = Manufacturer(name='eiki') m.models = [ Model(name='lc/xl200') ] m.models[0].sources = [ Source(pjlink_name='RGB1', pjlink_code='11', text='HDMI RGB'), Source(pjlink_name='RGB2', pjlink_code='12', text='VGA RGB') ] session.add(m) session.commit() p = session.query(Manufacturer, Model).\ options(joinedload(Manufacturer.models), joinedload(Model.sources)).\ filter(Manufacturer.name=='eiki', Model.name=='lc/xl200').\ all() m=p[0][0] print m.name print m.models[0].name for i in m.models[0].sources: print " PJLink name: %s code: %s Text: %s" % \ (i.pjlink_name, i.pjlink_code, i.text) -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.