【问题标题】:SQLAlchemy - Multiple Foreign key pointing to same table same attributeSQLAlchemy - 指向同一个表相同属性的多个外键
【发布时间】:2017-11-10 02:11:39
【问题描述】:

我的数据库结构....

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    user = db.relationship("BankSlip", back_populates="person_user")
    reference = db.relationship("BankSlip", back_populates="person_reference")

class BankSlip(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    person_user_id = db.Column(db.Integer, db.ForeignKey(Person.id))
    person_ref_id = db.Column(db.Integer, db.ForeignKey(Person.id))

    person_user = db.relationship("Person", back_populates="user", uselist=False, foreign_keys=[person_user_id])
    person_reference = db.relationship("Person", back_populates="reference", uselist=False, foreign_keys=[person_ref_id])

使用 Flask-SQLAlchemy 在 sqlite 上运行时出现以下错误

sqlalchemy.exc.AmbiguousForeignKeysError:无法确定关系 Person.user 上的父/子表之间的连接条件 - 有多个外键路径链接表。指定 'foreign_keys' 参数,提供应计为包含对父表的外键引用的列的列表。

这是我的pip freeze

appdirs==1.4.3
APScheduler==3.3.1
bcrypt==3.1.3
blinker==1.4
cffi==1.9.1
click==6.7
cssselect==1.0.1
cssutils==1.0.2
Flask==0.12
Flask-Login==0.4.0
Flask-Mail==0.9.1
Flask-Principal==0.4.0
Flask-SQLAlchemy==2.2
Flask-WTF==0.14.2
gunicorn==19.7.1
itsdangerous==0.24
Jinja2==2.9.5
lxml==3.7.3
MarkupSafe==1.0
nose==1.3.7
packaging==16.8
pkg-resources==0.0.0
premailer==3.0.1
pycparser==2.17
pyparsing==2.2.0
python-dateutil==2.6.0
pytz==2017.2
requests==2.13.0
schedule==0.4.2
six==1.10.0
SQLAlchemy==1.1.6
tzlocal==1.4
uWSGI==2.0.15
Werkzeug==0.12.1
WTForms==2.1

编辑:一张银行单可以有一个用户和一个参考......它应该是一对一的关系,其中parent -> childBankSlip -> UserBankSlip -> Reference。所以,一个孩子可以有多个父母!

【问题讨论】:

  • 那仍然不需要uselist=False BankSlip。 person_userperson_reference 仍然是单独的一对多关系,其中许多 BankSlips 可以与一个人相关。如果要一对一,请在 Person 一侧定义 uselist=False。这是否意味着 BankSlip 可以具有用户关系或引用关系,但不能同时具有两者?
  • 对不起,混淆了顺序,BankSlip 中的关系是多对一的,Person 中的关系是一对多的。尽管如此,还是对 Person 的关系有用。
  • 非常感谢!我把 121 和 12n 混在一起了。 uselist 应该是 True 或 default....
  • 另外,你认为这是错误的例子吗? docs.sqlalchemy.org/en/latest/orm/…
  • 不,请注意,在后一个示例中,关系是多对一的,即一个孩子可以有多个父母(外键在父母中),所以这就是为什么论点是关于孩子的关系一对一。

标签: python sqlite sqlalchemy flask-sqlalchemy entity-relationship


【解决方案1】:

按照错误消息的指示提供所需的 foreign_keys 参数:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    user = db.relationship("BankSlip", foreign_keys='BankSlip.person_user_id', back_populates="person_user")
    reference = db.relationship("BankSlip", foreign_keys='BankSlip.person_ref_id', back_populates="person_reference")

使用声明式you can define the foreign keys as a string,这将有助于解决循环依赖。或者,您可以使用 backref 而不是 back_populates:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)


class BankSlip(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    person_user_id = db.Column(db.Integer, db.ForeignKey(Person.id))
    person_ref_id = db.Column(db.Integer, db.ForeignKey(Person.id))

    person_user = db.relationship("Person", backref="user", uselist=False, foreign_keys=[person_user_id])
    person_reference = db.relationship("Person", backref="reference", uselist=False, foreign_keys=[person_ref_id])

请注意,uselist=False 位于关系的错误末尾,或者它是多余的,因为一个 Person 可以被多个 BankSlips 引用。它属于 Persons 这边,所以:

from sqlalchemy.orm import backref

...
    person_user = db.relationship("Person", backref=backref("user", uselist=False), foreign_keys=[person_user_id])
    person_reference = db.relationship("Person", backref=backref("reference", uselist=False), foreign_keys=[person_ref_id])

【讨论】:

    猜你喜欢
    • 2013-06-03
    • 2017-01-09
    • 1970-01-01
    • 2021-10-25
    • 2016-12-07
    • 1970-01-01
    相关资源
    最近更新 更多