繁体   English   中英

SqlAlchemy 多对多关系上的外键错误

[英]SqlAlchemy Foreign Key Error on Many to Many Relationship

我正在尝试在 SqlAlchemy 中建立基本的多对多关系。 我能够使用 db.create_all() 成功创建数据库,但是在尝试从数据库中检索任何记录时遇到错误。

class Geo(db.Model):
    __tablename__ = 'geos'

    geo = db.Column(db.Integer, primary_key=True)
    states = db.relationship("State", secondary='geos_states')



class State(db.Model):
    __tablename__ = 'states'

    state_short = db.Column(db.String, primary_key=True)
    geos = db.relationship("Geo", secondary='geos_states')



class GeoState(db.Model):
    __tablename__ = 'geos_states'

    id = db.Column(db.Integer, primary_key=True)
    geo_id = db.Column(db.Integer, db.ForeignKey('geos.geo')),
    state_short_id = db.Column(db.String, db.ForeignKey('states.state_short'))

错误如下:

sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.  Original exception was: Could not determine join condition between parent/child tables on relationship Geo.states - there are no foreign keys linking these tables via secondary table 'geos_states'.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify 'primaryjoin' and 'secondaryjoin' expressions.

您使用的模式是 SQLAlchemy 中多对多关系模式的变体。

通常你会做的是以下

geostates_association_table = Table(
    'geo_states', Base.metadata,
    db.Column(
        'geo_id', db.Integer, 
        db.ForeignKey('geos.geo')
    ),
    db.Column(
        'state_short_id', db.String,
        db.ForeignKey('states.state_short')
    )
)
    

class Geo(db.Model):
    __tablename__ = 'geos'

    geo = db.Column(db.Integer, primary_key=True)
    states = db.relationship(
        "State",
        secondary= geostates_association_table,
        back_populates='geos'
    )

class State(db.Model):
    __tablename__ = 'states'

    state_short = db.Column(
        db.String, 
        primary_key=True
    )
    geos = db.relationship(
       "Geo", 
       secondary=geostates_association_table,
       back_populates='states'
    )

我认为这是您所需要的,因为在多对多关系中的映射表上似乎不需要任何其他列。 但是,如果您这样做了,则需要使用您最初正在做的 Association Object 模式。 在这种情况下

class Geo(db.Model):
    __tablename__ = 'geos'

    geo = db.Column(
        db.Integer,
        primary_key=True
    )
    states = db.relationship(
        "GeoState",
        back_populates="geos"
    )



class State(db.Model):
    __tablename__ = 'states'

    state_short = db.Column(
        db.String, 
        primary_key=True
    )
    geos = db.relationship(
        "GeoState",
         back_populates="states"
    )



class GeoState(db.Model):
    __tablename__ = 'geos_states'
    # Notice how we set primary keys on both the fields
    geo_id = db.Column(
        db.Integer,
        db.ForeignKey('geos.geo'),
        primary_key=True
    ),
    state_short_id = db.Column(
        db.String,
        db.ForeignKey('states.state_short'),
        primary_key=True
    ),
    some_other_field = db.Column(
       db.String
    )

    geos = relationship("Geo", back_populates="states")
    states = relationship("State", back_populates="geos")

请注意,在这种情况下,您将在StateGeo的关系列表中获得的内容实际上是GeoState对象。 如果您想使用关联 Object 模式,但让关系列表由它们各自的对应对象填充。 您可以使用 AssociationProxy sqlalchemy 扩展,您可以在此处找到文档

供你参考,

此处记录了关联 Object 模式

此处记录了基本的多对多模式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM