Why am I getting AmbiguousForeignKeysError?

后端 未结 2 362
青春惊慌失措
青春惊慌失措 2021-01-27 04:54

I\'ve run into an issue after following the SqlAlchemy guide here.

Given the following simplified module:

class _Base():
    id_ = Column(Integer, primary_         


        
2条回答
  •  深忆病人
    2021-01-27 05:50

    The issue is with the definition of this relationship match = relationship("MatchResult") for the Player class. If you completely remove this line, and use the below definitions for the relationships, all the queries you mentioned should work as expected:

    class Player(Base, BlgMixin):
        __tablename__ = "player"
    
        name_ = Column(String(100))
    
    
    class MatchResult(Base, BlgMixin):
        __tablename__ = "match_result"
    
        p1_id = Column(ForeignKey(Player.id_))
        p2_id = Column(ForeignKey(Player.id_))
    
        p1 = relationship(Player, foreign_keys=p1_id)
        p2 = relationship(Player, foreign_keys=p2_id)
    

    In fact, the desired select query can also be constructed, but you need to specify the relationships explicitly on JOINs:

    player_1 = aliased(Player)
    player_2 = aliased(Player)
    q = (
        dal.session
        .query(
            MatchResult.p1_id,
            player_1.name_,
            MatchResult.p2_id,
            player_2.name_,
        )
        .join(player_1, MatchResult.p1)  # explicitly specify which relationship/FK to join on
        .join(player_2, MatchResult.p2)  # explicitly specify which relationship/FK to join on
    )
    

    I would, however, make few more changes to the model to make it even more user-friednly:

    1. add backref to the relationship so that it can be navigated back from the Player
    2. add a property to show all the matches of one player for both sides

    Model definitions:

    class Player(Base, BlgMixin):
        __tablename__ = "player"
    
        name_ = Column(String(100))
    
        @property
        def all_matches(self):
            return self.matches_home + self.matches_away
    
    
    class MatchResult(Base, BlgMixin):
        __tablename__ = "match_result"
    
        p1_id = Column(ForeignKey(Player.id_))
        p2_id = Column(ForeignKey(Player.id_))
        
        p1 = relationship(Player, foreign_keys=p1_id, backref="matches_home")
        p2 = relationship(Player, foreign_keys=p2_id, backref="matches_away")
    

    This will allow navigating the relationships as per below example:

    p1 = session.query(Player).get(1)
    print(p1)
    for match in p1.all_matches:
        print(" ", match)
    

提交回复
热议问题