簡體   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