giu*_*tte 3 python orm sqlalchemy foreign-keys relationship
我正在尝试使用几个相关模型构建一个示例,如下所示。我们有一个模型 B 与模型 C 具有 1:n 关系;那么我们就有一个模型 A,与 B 具有 1 关系,与 C 具有 1 关系。(C 有 2 列主键)
我尝试了这段代码:
class C(db.Model):
__tablename__ = 'C'
key1 = Column(Integer, primary_key=True)
key2 = Column(Integer, primary_key=True)
attr1 = Column(Date)
attr2 = Column(Boolean)
related_b = Column(Integer, ForeignKey('B.spam'))
class B(db.Model):
__tablename__ = 'B'
spam = Column(Integer, default=1, primary_key=True)
eggs = Column(String, default='eggs')
null = Column(String)
n_relation = relationship(C, foreign_keys='C.related_b')
class A(db.Model):
__tablename__ = 'A'
foo = Column(String, default='foo', primary_key=True)
bar = Column(String, default='bar', primary_key=True)
baz = Column(String, default='baz')
rel = relationship(B, foreign_keys='A.related_b')
related_b = Column(Integer, ForeignKey('B.spam'))
related_c1 = Column(Integer, ForeignKey('C.key1'))
related_c2 = Column(Integer, ForeignKey('C.key2'))
other_rel = relationship(C, foreign_keys=(related_c1, related_c2))
Run Code Online (Sandbox Code Playgroud)
只是为了得到例外:
sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship A.other_rel - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.
Run Code Online (Sandbox Code Playgroud)
但是嘿,我已经通过了这个论点。我尝试了该参数的各种版本,通过名称指定 A 列,通过名称指定 C 列,通过直接引用指定 C 列,似乎没有什么会影响此错误。我还尝试使用单个复合外键,如下所示:
class A(db.Model):
__tablename__ = 'A'
foo = Column(String, default='foo', primary_key=True)
bar = Column(String, default='bar', primary_key=True)
baz = Column(String, default='baz')
rel = relationship(B, foreign_keys='A.related_b')
related_b = Column(Integer, ForeignKey('B.spam'))
related_c1 = Column(Integer, ForeignKey('C.key1'))
related_c2 = Column(Integer, ForeignKey('C.key2'))
compound = ForeignKeyConstraint(('related_c1', 'related_c2'), ('C.key1', 'C.key2'))
other_rel = relationship(C, foreign_keys=compound)
Run Code Online (Sandbox Code Playgroud)
但一切都没有改变。我是否弄错了什么或者这是一个错误?(至少,错误消息不正确......)
这里的问题是你必须在类ForeignKeyConstraint()中声明__table_args__,而不是在类的主体中。
换句话说,以下代码不会将外键约束应用于子表 \xe2\x80\xa6
\nfrom sqlalchemy import create_engine, Column, Integer, text, ForeignKeyConstraint, String\nfrom sqlalchemy.orm import declarative_base, relationship\n\nconnection_url = r"mssql+pyodbc://@.\\SQLEXPRESS/myDb?driver=ODBC+Driver+17+for+SQL+Server"\nengine = create_engine(connection_url)\nBase = declarative_base()\n\n\nclass Parent(Base):\n __tablename__ = "tbl_parent"\n id1 = Column(Integer, primary_key=True)\n id2 = Column(Integer, primary_key=True)\n parent_name = Column(String(50))\n children = relationship("Child", back_populates="parent")\n\n\nclass Child(Base):\n __tablename__ = "tbl_child"\n id = Column(Integer, primary_key=True, autoincrement=False)\n child_name = Column(String(50))\n parent_id1 = Column(Integer)\n parent_id2 = Column(Integer)\n # this does not work\n ForeignKeyConstraint(\n ["parent_id1", "parent_id2"], ["tbl_parent.id1", "tbl_parent.id2"]\n )\n parent = relationship(\n "Parent",\n foreign_keys="[Child.parent_id1, Child.parent_id2]",\n back_populates="children",\n )\n\n\nBase.metadata.drop_all(engine)\nengine.echo = True\nBase.metadata.create_all(engine)\n\n"""DDL emitted:\nCREATE TABLE tbl_parent (\n id1 INTEGER NOT NULL, \n id2 INTEGER NOT NULL, \n parent_name VARCHAR(50), \n PRIMARY KEY (id1, id2)\n)\nCREATE TABLE tbl_child (\n id INTEGER NOT NULL, \n child_name VARCHAR(50), \n parent_id1 INTEGER, \n parent_id2 INTEGER, \n PRIMARY KEY (id)\n)\n"""\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x80\xa6 但这可以工作 \xe2\x80\xa6
\nfrom sqlalchemy import create_engine, Column, Integer, text, ForeignKeyConstraint, String\nfrom sqlalchemy.orm import declarative_base, relationship\n\nconnection_url = r"mssql+pyodbc://@.\\SQLEXPRESS/myDb?driver=ODBC+Driver+17+for+SQL+Server"\nengine = create_engine(connection_url)\nBase = declarative_base()\n\n\nclass Parent(Base):\n __tablename__ = "tbl_parent"\n id1 = Column(Integer, primary_key=True)\n id2 = Column(Integer, primary_key=True)\n parent_name = Column(String(50))\n children = relationship("Child", back_populates="parent")\n\n\nclass Child(Base):\n __tablename__ = "tbl_child"\n # this works\n __table_args__ = (\n ForeignKeyConstraint(\n ["parent_id1", "parent_id2"], ["tbl_parent.id1", "tbl_parent.id2"]\n ),\n )\n id = Column(Integer, primary_key=True, autoincrement=False)\n child_name = Column(String(50))\n parent_id1 = Column(Integer)\n parent_id2 = Column(Integer)\n\n parent = relationship(\n "Parent",\n foreign_keys="[Child.parent_id1, Child.parent_id2]",\n back_populates="children",\n )\n\n\nBase.metadata.drop_all(engine)\nengine.echo = True\nBase.metadata.create_all(engine)\n\n"""DDL emitted:\nCREATE TABLE tbl_parent (\n id1 INTEGER NOT NULL, \n id2 INTEGER NOT NULL, \n parent_name VARCHAR(50) NULL, \n PRIMARY KEY (id1, id2)\n)\nCREATE TABLE tbl_child (\n id INTEGER NOT NULL, \n child_name VARCHAR(50) NULL, \n parent_id1 INTEGER NULL, \n parent_id2 INTEGER NULL, \n PRIMARY KEY (id), \n FOREIGN KEY(parent_id1, parent_id2) REFERENCES tbl_parent (id1, id2)\n)\n"""\nRun Code Online (Sandbox Code Playgroud)\n参考:
\nhttps://docs.sqlalchemy.org/en/14/orm/declarative_tables.html#orm-declarative-table-configuration
\n