python - datatypes - foreign key flask sqlalchemy
SQLAlchemy varias claves foráneas en una clase asignada a la misma clave primaria (2)
Estoy intentando configurar una tabla postgresql que tiene dos claves externas que apuntan a la misma clave principal en otra tabla.
Cuando ejecuto el script me sale el error
sqlalchemy.exc.AmbiguousForeignKeysError: No se pudo determinar la condición de unión entre las tablas padre / hijo en la relación Company.stakeholder: hay varias rutas de clave externa que vinculan las tablas. Especifique el argumento ''foreign_keys'', que proporciona una lista de aquellas columnas que deben contarse como que contienen una referencia de clave externa a la tabla principal.
Ese es el error exacto en la documentación de SQLAlchemy, pero cuando replico lo que han ofrecido como solución, el error no desaparece. ¿Qué podría estar haciendo mal?
#The business case here is that a company can be a stakeholder in another company.
class Company(Base):
__tablename__ = ''company''
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
class Stakeholder(Base):
__tablename__ = ''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'')
He visto preguntas similares aquí, pero algunas de las respuestas recomiendan que se use una primaryjoin
sin embargo, en la documentación se indica que no necesita la primaryjoin
en esta situación.
Intenté eliminar las comillas de las teclas_exteriores y hacerlas una lista. De la documentación oficial sobre la Relationship Configuration: Handling Multiple Join Paths
Cambiado en la versión 0.8:
relationship()
puede resolver la ambigüedad entre los objetivos de clave externa solo en base al argumentoforeign_keys
; el argumento deprimaryjoin
ya no es necesario en esta situación.
El siguiente código autónomo funciona con 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):
__tablename__ = ''company''
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
class Stakeholder(Base):
__tablename__ = ''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 última documentación:
La forma de foreign_keys=
en la documentación produce un NameError, sin estar seguro de cómo se espera que funcione cuando la clase aún no se ha creado. Con algo de hacking pude tener éxito con esto:
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 otras palabras:
… foreign_keys=''CurrentClass.thing_id'')