hi, i think i've hit another 2 bugs/features today. #1 AFAICS there's something with the mapper inheritance, that makes cascade="all, delete-orphaned" not working. #2 i'm getting an error when i try to access a polymorphic property, if some of it's contained objects has a defered property.
thanks for your help in advance!
from sqlalchemy import * from datetime import datetime metadata = BoundMetaData('sqlite:///', echo=False) products_table = Table('products', metadata, Column('product_id', Integer, primary_key=True), Column('product_type', String(128)), Column('name', String(128)), Column('mark', String(128)), Column('material', String(128), default=''), Column('sortament', String(128), default=''), Column('weight', String(128), default=''), ) specification_table = Table('specification', metadata, Column('spec_line_id', Integer, primary_key=True), Column('master_id', Integer, ForeignKey("products.product_id"), nullable=True), Column('slave_id', Integer, ForeignKey("products.product_id"), nullable=True), Column('quantity', Float, default=1.), ) documents_table = Table('documents', metadata, Column('document_id', Integer, primary_key=True), Column('document_type', String(128)), Column('product_id', Integer, ForeignKey('products.product_id')), Column('create_date', DateTime, default=lambda:datetime.now()), Column('last_updated', DateTime, default=lambda:datetime.now(), onupdate=lambda:datetime.now()), Column('name', String(128)), Column('data', Binary), Column('size', Integer, default=0), ) metadata.create_all() class Product(object): def __init__(self, name, mark=''): self.name = name self.mark = mark def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.name) class Detail(Product): def __init__(self, name, mark='', material='', sortament='', weight=''): self.name = name self.mark = mark self.material = material self.sortament = sortament self.weight = weight class Assembly(Product): pass class SpecLine(object): def __init__(self, master=None, slave=None, quantity=1): self.master = master self.slave = slave self.quantity = quantity def __repr__(self): return '<%s %.01f %s>' % ( self.__class__.__name__, self.quantity or 0., getattr(self.slave, 'name', None) ) class Document(object): def __init__(self, name, data=None): self.name = name self.data = data def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.name) class RasterDocument(Document): pass product_mapper = mapper(Product, products_table, polymorphic_on=products_table.c.product_type, polymorphic_identity='product') detail_mapper = mapper(Detail, inherits=product_mapper, polymorphic_identity='detail') assembly_mapper = mapper(Assembly, inherits=product_mapper, polymorphic_identity='assembly') specification_mapper = mapper(SpecLine, specification_table, properties=dict( master=relation(Assembly, lazy=False, uselist=False, foreignkey=specification_table.c.master_id, primaryjoin=specification_table.c.master_id==products_table.c.product_id, backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), ), slave=relation(Product, lazy=False, uselist=False, foreignkey=specification_table.c.slave_id, primaryjoin=specification_table.c.slave_id==products_table.c.product_id, ), quantity=specification_table.c.quantity, ) ) document_mapper = mapper(Document, documents_table, polymorphic_on=documents_table.c.document_type, polymorphic_identity='document', properties=dict( name=documents_table.c.name, data=deferred(documents_table.c.data), product=relation(Product, lazy=True, backref='documents'), ), ) raster_document_mapper = mapper(RasterDocument, inherits=document_mapper, polymorphic_identity='raster_document') assembly_mapper.add_property('specification', relation(SpecLine, lazy=True, primaryjoin=specification_table.c.master_id==products_table.c.product_id, backref='master', cascade='all, delete-orphan', ) ) # bug #1 # the property must be added to all the mapers individually, else delete-orphan doesnt work for m in (product_mapper, assembly_mapper, detail_mapper): m.add_property('documents', relation(Document, lazy=True, backref='product', cascade='all, delete-orphan'), ) session = create_session() a1 = Assembly(name='a1') a1.specification.append(SpecLine(slave=Detail(name='d1'))) a1.documents.append(Document('doc1')) a1.documents.append(RasterDocument('doc2')) # bug #2 session.save(a1) session.flush() session.clear() del a1 a1 = session.query(Product).get_by(name='a1') print a1.documents