Michael, I looked at the code and I can not say more than that its very interesting, I have to see how it works and more importantly how It fits into my objects but it seems clear enough to do so. I really appreciate your work on SQLAlchemy and all the time you spend to help us "users" out.
Your solution is definitively one I could not have put together myself. Although I have tried. SQLAlchemy is so powerful that it is hard to find "the right options" for the job. Thank you again! Martijn On Feb 13, 2011, at 21:19 , Michael Bayer wrote: > > On Feb 13, 2011, at 6:14 AM, Martijn Moeling wrote: > >> You are right in the misunderstood relation. >> >> I see the primary key in extra to be wrong, extra should have it's own I'd >> column being an auto number. In extra it should be possible to have many >> records pointing to 1 ext variant. Sorry for that. >> >> The extra, should also work with tables without a discriminator, there the >> link should be made to table name which is in my case always class.__name__ >> ...... On those tables, the relation needs to be different since on of the >> "local" columns, discriminator is not present and it somehow should be >> linked to __table name__ > > OK what you are trying to do is exactly a "polymorphic association". The > technique of placing "tablename" in the table of "related" records, then > using that "tablename" to indicate which parent table should be matched at > query time, is a common, but IMHO relationally incorrect pattern. I blogged > extensively about the Ruby on Rails approach, how to duplicate Rails' > approach in SQLAlchemy, and then an alternate system which maintains > referential integrity, four years ago at > http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-sqlalchemy/ > . > > That's a really old example and we're into 0.7 now, so I've created a new > version of the poly assoc example that uses declarative techniques and the > association proxy, which is attached. I'm going to further fix up this > example and add it to the distribution as a fourth example of polymorphic > association, which is in examples/poly_assoc/. > > Additionally I'd like the association proxy to work more smoothly in queries > so I've added ticket #2054 for some of those issues which weren't accounted > for when we first added any(), contains() operators to the association proxy. > > > > > >> >> It is all part of the ACL examples it talked about walker, where extra must >> be seen as the ACL. That is where the mapper extension comes in.... >> >> It is getting a "all technologies" mixed in situation >> >> Verstuurd vanaf mijn iPad >> >> Op Feb 12, 2011 om 17:05 heeft "Michael Bayer" <mike...@zzzcomputing.com> >> het volgende geschreven: >> >>> OK I can show you the version of your code that does most of this but there >>> are some fundamental relational misunderstandings in this schema if I am >>> interpreting correctly. >>> >>> Extra: >>> >>> tableid tablename >>> ------- --------- >>> 1 ext1 >>> 2 ext1 >>> 3 ext2 >>> 4 ext2 >>> 5 ext3 >>> >>> ext1: >>> >>> id discriminator (-> FK to Extra.tableid, Extra.tablename) >>> -- ------------- >>> 1 ext1 >>> 2 ext1 >>> 3 ext2 >>> 4 ext2 >>> 5 ext3 >>> >>> ext2: >>> >>> id >>> -- >>> 3 >>> 4 >>> >>> ext3: >>> >>> id >>> -- >>> >>> 5 >>> >>> given ext1 ID #3, discriminator "ext2" - how can more than one Extra row be >>> referenced? Why is "extras" assumed to be one-to-many when it can only be >>> many-to-one ? >>> >>> >>> >>> >>> >>> >>> On Feb 12, 2011, at 9:57 AM, Martijn Moeling wrote: >>> >>>> This whole thing is driving me crazy, What I want: >>>> >>>> >>>> >>>> class Extra(Base): >>>> __tablename__ = "extra" >>>> # Primary key consists of two different columns !!! >>>> tableId = Column(Integer, primary_key=true) >>>> tablename = Column(Unicode(20), primary_key=True) >>>> >>>> info = Column(........) #Not relevant >>>> >>>> >>>> >>>> >>>> class ex1(Base): >>>> Id = Column(Integer, primary_key=True) >>>> discriminator = Column(Unicode(20)) >>>> >>>> @declared_attr >>>> def __tablename__(self): >>>> return self.__name__.lower() >>>> >>>> @declared_attr >>>> def __mapper_args__(self): >>>> if self.__name__ == 'ext1': >>>> return {'polymorphic_on': self.discriminator, >>>> 'polymorphic_identity':unicode(self.__name__.lower()), >>>> 'extension': FilePropertiesMapperExtension(), >>>> 'batch' : False} >>>> else: >>>> return {'polymorphic_identity':unicode(self.__name__.lower()), >>>> 'inherit_condition': self.Id == extra.Id, >>>> #needed for something else in this config (multiple self reference) >>>> 'extension': FilePropertiesMapperExtension(), >>>> #Needed for something else, not relevant for this sample >>>> 'batch' : False} >>>> # ,, ,, ,, ,, >>>> >>>> >>>> # Set up foreignkey and relation to Extra.... >>>> __table_args__ = (ForeignKeyConstraint(['discriminator', 'Id'], >>>> ['extra.Table','extra.TableId']),{}) >>>> >>>> >>>> extras = relation('Extra', cascade="all", lazy="dynamic" >>>> backref="owner") >>>> >>>> >>>> .... >>>> .... >>>> >>>> >>>> class ext2(ext1): >>>> Id = Column(Integer,ForeignKey('ext1.Id'), >>>> primary_key=True) >>>> ...... >>>> >>>> >>>> class ext3(ext1): >>>> Id = Column(Integer,ForeignKey('ext1.Id'), >>>> primary_key=True) >>>> ..... >>>> >>>> >>>> >>>> >>>> Now I want: >>>> >>>> Ext2 = ext2() >>>> Extra_info = extra() >>>> Ext2.extras.append(Extra_Info) >>>> >>>> >>>> Ext2.discriminator should be "ext2" >>>> Ext2.Id should be 1 for the first record >>>> >>>> Extra_Info should be created in the database, with its columns : id set to >>>> the Ext2.id and tablename to Ext.discriminator ...... >>>> Extra_Info.owner would point to Ext2 >>>> >>>> If Ext2 is deleted, all related extrainfo record would be delete too >>>> >>>> if one Extra_Info is deleted, Extra_Info.owner should stay in place as >>>> well as all other related >>>> >>>> Extra is many to one polymorhic version of ext1 >>>> >>>> I hope this clarifies more what I want.... >>>> >>>> I really need the @declared_attr way of doing stuff and that is not >>>> related to this question but might influence this question so I left it >>>> in...... >>>> >>>> Martijn >>>> >>>> >>>> On Feb 10, 2011, at 18:13 , Michael Bayer wrote: >>>> >>>>> >>>>> On Feb 10, 2011, at 4:20 AM, Martijn Moeling wrote: >>>>> >>>>>> Another small thing: >>>>>> >>>>>> I took a look at: >>>>>> >>>>>> ForeignKeyConstraint(['invoice_id', 'ref_num'], ['invoice.invoice_id', >>>>>> 'invoice.ref_num']) >>>>>> >>>>>> Now for Polymorphic tables: >>>>>> >>>>>> >>>>>> in baseclass: >>>>>> >>>>>> baseclass.discriminator happens to be the __tablename__ of the >>>>>> polymorphic >>>>>> >>>>>> ForeignKeyConstraint('['baseclass.disciminator', baseclass.Id'], >>>>>> ['someotherclass.tablename','someotherclass.tableId'] >>>>>> relationship('someotherclass', backref=baseclass, cascade="all", >>>>>> lazy="dynamic") >>>>>> >>>>>> >>>>>> in someotheclass: >>>>>> >>>>>> tablename = column(Unicode(20), primary_key=True) >>>>>> tableId = column(Integer, primary_key=True) >>>>>> >>>>>> seems Ok to me. >>>>>> >>>>>> Now I need to make someotherclass work with non-polymorphic tables too!! >>>>>> >>>>>> anotherclass: >>>>>> Id = column(Integer, primary_key=True) >>>>>> >>>>>> ForeignKeyConstaint('[anotherclass.__tablename__,'anotherclass.Id'],['someotherclass.tablename','someotherclass.tableId']) >>>>>> relation('someotherclass', backref=baseclass, cascade="all", >>>>>> lazy="dynamic") >>>>>> >>>>>> Is there any way to get this working without configuring it as >>>>>> polymorphic an do no Inhiritance, I do not want each anotherclass record >>>>>> to have a column discriminator with its own tablename! >>>>>> >>>>>> or can I use anotherclass.__tablename__ in the ForeignKeyConstaint? >>>>>> >>>>>> This has to do with the someotherclass being the "ACL" I talked about in >>>>>> a previous post if that gives extra info. I am trying to implement the >>>>>> MapperExtension.before_append where I need to refer to the "ACL" records >>>>>> in a way like: >>>>>> >>>>>> for A in instance.ACL: >>>>>> ..... >>>>> >>>>> yeah, sorry, this use case continues to be 98% opaque to me. I don't >>>>> understand what you mean by "make someotherclass work with >>>>> non-polymorphic tables", a class is mapped in just one way, either with >>>>> or without a discriminator column. A single class can't be mapped in >>>>> both ways. If there's no discriminator, there's just one class that >>>>> can be used for returned rows. >>>>> >>>>> If you could create a small test that illustrates a mapping and an >>>>> expected result, perhaps I can attempt to find a way to get the ORM >>>>> behavior you're looking for. >>>>> >>>>> Your mapper extension would continue to be used normally with a "dynamic" >>>>> relationship since it uses query(cls) just like a regular query. >>>>> >>>>> >>>>> >>>>> -- >>>>> 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. >>>>> >>>> >>>> -- >>>> 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. >>>> >>> >>> -- >>> 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. >>> >> >> -- >> 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. >> > > <martijnmoeling.py>-- > 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. > -- 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.