On Feb 13, 2014, at 12:16 PM, Michael Hipp <[email protected]> wrote:
> On 2/13/2014 11:04 AM, Michael Bayer wrote: >> On Feb 13, 2014, at 11:53 AM, Michael Hipp <[email protected]> wrote: >> >> I don't see a "first_owner" relationship defined above, so the above example >> is not complete. The approach using "foreign_keys" is the correct approach >> to resolving ambiguity in join conditions, however. If the documented >> approach is not working you'd need to provide a succinct self-contained >> example I can run. > > Sorry, it was tripping over a different error, here's the code with extras > removed (I think!): > > class Animal(Base): > __tablename__ = 'animals' > id_ = Column(Integer, primary_key=True) > > sire_id = Column(Integer, ForeignKey('animals.id_')) > dam_id = Column(Integer, ForeignKey('animals.id_')) > > sire = relationship('Animal', foreign_keys=[sire_id]) > dam = relationship('Animal', foreign_keys=[dam_id]) > children = relationship('Animal', foreign_keys=[sire_id, dam_id]) > > Gives: > sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition > between parent/child tables on relationship Animal.children - there are > multiple foreign key paths linking the tables. Specify the 'foreign_keys' > argument, providing a list of those columns which should be counted as > containing a foreign key reference to the parent table. OK so there’s more subtlety here. When SQLA makes a “join condition” between two tables (or the same table), it looks for essentially a single ForeignKeyConstraint object (note that this is distinct from the ForeignKey construct used above) with which to create that join. It never uses multiple FKC’s to do so. So above, each individual ForeignKey() results in the implicit creation of a ForeignKeyConstraint object on the “animals” table. In other cases (not this one), multiple columns might be bundled into a single ForeignKeyConstraint, when the construct is used explicitly, this is called a composite foreign key constraint. The “foreign_keys” argument essentially provides a hint to this which says, “use the foreign key constraint associated with this column”, but at the moment the limitation for “only one FKC can be selected” still applies there (this is an odd case). So for “children” above you need to spell out primaryjoin completely which is primaryjoin=“and_(Animal.sire_id == Animal.id_, Animal.dam_id == Animal.id)”.
signature.asc
Description: Message signed with OpenPGP using GPGMail
