J'essaie de configurer une table postgresql qui a deux clés étrangères qui pointent vers la même clé primaire dans une autre table.
Lorsque j'exécute le script, j'obtiens l'erreur
sqlalchemy.exc.AmbiguousForeignKeysError: impossible de déterminer la condition de jointure entre les tables parent/enfant sur la relation Company.stakeholder - il existe plusieurs chemins d'accès de clé étrangère reliant les tables. Spécifiez l'argument 'foreign_keys', en fournissant une liste des colonnes qui doivent être comptées comme contenant une référence de clé étrangère vers la table parent.
C'est l'erreur exacte dans la Documentation SQLAlchemy pourtant quand je réplique ce qu'ils ont proposé comme solution, l'erreur ne disparaît pas. Que pourrais-je faire de mal?
#The business case here is that a company can be a stakeholder in another company.
class Company(Base):
__table= 'company'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
class Stakeholder(Base):
__table= 'stakeholder'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey('company.id'), nullable=False)
stakeholder_id = Column(Integer, ForeignKey('company.id'), nullable=False)
company = relationship("Company", foreign_keys='company_id')
stakeholder = relationship("Company", foreign_keys='stakeholder_id')
J'ai vu des questions similaires ici mais certaines des réponses recommandez que l'on utilise un primaryjoin
pourtant dans la documentation il indique que vous n'avez pas besoin du primaryjoin
dans cette situation .
J'ai essayé de supprimer les guillemets des Foreign_keys et d'en faire une liste. De la documentation officielle sur Relationship Configuration: Handling Multiple Join Paths
Modifié dans la version 0.8:
relationship()
peut résoudre l'ambiguïté entre les cibles de clés étrangères sur la seule base de l'argumentforeign_keys
; l'argumentprimaryjoin
n'est plus nécessaire dans cette situation.
Le code autonome ci-dessous fonctionne avec sqlalchemy>=0.9
:
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine(u'sqlite:///:memory:', echo=True)
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()
#The business case here is that a company can be a stakeholder in another company.
class Company(Base):
__table= 'company'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
class Stakeholder(Base):
__table= 'stakeholder'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey('company.id'), nullable=False)
stakeholder_id = Column(Integer, ForeignKey('company.id'), nullable=False)
company = relationship("Company", foreign_keys=[company_id])
stakeholder = relationship("Company", foreign_keys=[stakeholder_id])
Base.metadata.create_all(engine)
# simple query test
q1 = session.query(Company).all()
q2 = session.query(Stakeholder).all()
La dernière documentation:
La forme de foreign_keys=
dans la documentation produit une erreur NameError, je ne sais pas comment elle devrait fonctionner lorsque la classe n'a pas encore été créée. Avec du piratage, j'ai réussi à réussir:
company_id = Column(Integer, ForeignKey('company.id'), nullable=False)
company = relationship("Company", foreign_keys='Stakeholder.company_id')
stakeholder_id = Column(Integer, ForeignKey('company.id'), nullable=False)
stakeholder = relationship("Company",
foreign_keys='Stakeholder.stakeholder_id')
En d'autres termes:
… foreign_keys='CurrentClass.thing_id')