• <legend id='QtpRg'><style id='QtpRg'><dir id='QtpRg'><q id='QtpRg'></q></dir></style></legend>

      <tfoot id='QtpRg'></tfoot>

      <small id='QtpRg'></small><noframes id='QtpRg'>

      • <bdo id='QtpRg'></bdo><ul id='QtpRg'></ul>
      <i id='QtpRg'><tr id='QtpRg'><dt id='QtpRg'><q id='QtpRg'><span id='QtpRg'><b id='QtpRg'><form id='QtpRg'><ins id='QtpRg'></ins><ul id='QtpRg'></ul><sub id='QtpRg'></sub></form><legend id='QtpRg'></legend><bdo id='QtpRg'><pre id='QtpRg'><center id='QtpRg'></center></pre></bdo></b><th id='QtpRg'></th></span></q></dt></tr></i><div id='QtpRg'><tfoot id='QtpRg'></tfoot><dl id='QtpRg'><fieldset id='QtpRg'></fieldset></dl></div>

        SQLAlchemy ORM 不能使用复合外键

        时间:2023-08-30

          <tbody id='Husn5'></tbody>
        • <i id='Husn5'><tr id='Husn5'><dt id='Husn5'><q id='Husn5'><span id='Husn5'><b id='Husn5'><form id='Husn5'><ins id='Husn5'></ins><ul id='Husn5'></ul><sub id='Husn5'></sub></form><legend id='Husn5'></legend><bdo id='Husn5'><pre id='Husn5'><center id='Husn5'></center></pre></bdo></b><th id='Husn5'></th></span></q></dt></tr></i><div id='Husn5'><tfoot id='Husn5'></tfoot><dl id='Husn5'><fieldset id='Husn5'></fieldset></dl></div>

              <small id='Husn5'></small><noframes id='Husn5'>

              • <tfoot id='Husn5'></tfoot>
              • <legend id='Husn5'><style id='Husn5'><dir id='Husn5'><q id='Husn5'></q></dir></style></legend>
                  <bdo id='Husn5'></bdo><ul id='Husn5'></ul>
                  本文介绍了SQLAlchemy ORM 不能使用复合外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我正在尝试使用几个相关模型构建一个示例,如下所示.我们有一个模型 B 与模型 C 的关系为 1:n;那么我们有一个模型 A,它与 B 的关系为 n:1,与 C 的关系为 n:1.(C 有一个 2 列的主键)

                  I'm trying to build an example with several related models, like the following. We have a model B with a 1:n relation with a model C; then we have a model A with a n:1 relation with B and a n:1 relation with C. (C has a 2-columns primary key)

                  我试过这段代码:

                  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))
                  

                  只是为了获得例外:

                  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.
                  

                  但是,嘿,我已经通过了那个论点.我为该参数尝试了各种版本,指定 A 列,通过名称指定 C 列,通过直接引用指定 C 列,似乎没有任何影响此错误.我还尝试使用单个复合外键,如下所示:

                  but hey, I HAVE passed that argument. I tried various versions for that argument, specifying A columns, C columns via name, C columns via direct reference, nothing seems to affect this error. I also tried to use a single compound foreign key, like this:

                  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)
                  

                  但没有任何改变.我弄错了什么还是一个错误?(至少,错误信息不正确……)

                  but nothing changed. Am I mistaking something or is it a bug? (at least, the error message is not correct...)

                  推荐答案

                  这里的问题是你必须在 __table_args__ 中声明 ForeignKeyConstraint,而不是在班级.

                  The issue here is that you have to declare the ForeignKeyConstraint in __table_args__, not in the body of the class.

                  换句话说,以下代码不会将外键约束应用于子表...

                  In other words, the following code will NOT apply the foreign key constraint to the child table ...

                  from sqlalchemy import (
                      create_engine,
                      Column,
                      Integer,
                      text,
                      ForeignKeyConstraint,
                      String,
                  )
                  from sqlalchemy.ext.declarative import declarative_base
                  from sqlalchemy.orm import relationship
                  
                  connection_uri = (
                      r"mssql+pyodbc://@.SQLEXPRESS/myDb?driver=ODBC+Driver+17+for+SQL+Server"
                  )
                  engine = create_engine(connection_uri, echo=True,)
                  
                  with engine.connect() as conn:
                      for tb_name in ["tbl_child", "tbl_parent"]:
                          conn.execute(text(f"DROP TABLE IF EXISTS [{tb_name}]"))
                  
                  Base = declarative_base()
                  
                  
                  class Parent(Base):
                      __tablename__ = "tbl_parent"
                      id1 = Column(Integer, primary_key=True)
                      id2 = Column(Integer, primary_key=True)
                      parent_name = Column(String(50))
                      children = relationship("Child", back_populates="parent")
                  
                      def __repr__(self):
                          return f"<Parent(id1={self.id1}, id2={self.id2}), parent_name='{self.parent_name}'>"
                  
                  
                  class Child(Base):
                      __tablename__ = "tbl_child"
                      id = Column(Integer, primary_key=True, autoincrement=False)
                      child_name = Column(String(50))
                      parent_id1 = Column(Integer)
                      parent_id2 = Column(Integer)
                      ForeignKeyConstraint(
                          ["parent_id1", "parent_id2"], ["tbl_parent.id1", "tbl_parent.id2"]
                      )
                      parent = relationship(
                          "Parent",
                          foreign_keys="[Child.parent_id1, Child.parent_id2]",
                          back_populates="children",
                      )
                  
                      def __repr__(self):
                          return f"<Child(id={self.id}, child_name={self.child_name})>"
                  
                  
                  Base.metadata.create_all(engine)
                  
                  """ console output:
                  2020-04-30 06:57:13,899 INFO sqlalchemy.engine.Engine 
                  CREATE TABLE tbl_parent (
                      id1 INTEGER NOT NULL, 
                      id2 INTEGER NOT NULL, 
                      parent_name VARCHAR(50), 
                      PRIMARY KEY (id1, id2)
                  )
                  
                  
                  2020-04-30 06:57:13,899 INFO sqlalchemy.engine.Engine ()
                  2020-04-30 06:57:13,900 INFO sqlalchemy.engine.Engine COMMIT
                  2020-04-30 06:57:13,901 INFO sqlalchemy.engine.Engine 
                  CREATE TABLE tbl_child (
                      id INTEGER NOT NULL, 
                      child_name VARCHAR(50), 
                      parent_id1 INTEGER, 
                      parent_id2 INTEGER, 
                      PRIMARY KEY (id)
                  )
                  
                  
                  2020-04-30 06:57:13,901 INFO sqlalchemy.engine.Engine ()
                  2020-04-30 06:57:13,901 INFO sqlalchemy.engine.Engine COMMIT
                  """
                  

                  ...但是这 ...

                  from sqlalchemy import (
                      create_engine,
                      Column,
                      Integer,
                      text,
                      ForeignKeyConstraint,
                      String,
                  )
                  from sqlalchemy.ext.declarative import declarative_base
                  from sqlalchemy.orm import relationship
                  
                  connection_uri = (
                      r"mssql+pyodbc://@.SQLEXPRESS/myDb?driver=ODBC+Driver+17+for+SQL+Server"
                  )
                  # connection_uri = "sqlite:///:memory:"
                  engine = create_engine(connection_uri, echo=True,)
                  
                  with engine.connect() as conn:
                      for tb_name in ["tbl_child", "tbl_parent"]:
                          conn.execute(text(f"DROP TABLE IF EXISTS [{tb_name}]"))
                  
                  Base = declarative_base()
                  
                  
                  class Parent(Base):
                      __tablename__ = "tbl_parent"
                      id1 = Column(Integer, primary_key=True)
                      id2 = Column(Integer, primary_key=True)
                      parent_name = Column(String(50))
                      children = relationship("Child", back_populates="parent")
                  
                      def __repr__(self):
                          return f"<Parent(id1={self.id1}, id2={self.id2}), parent_name='{self.parent_name}'>"
                  
                  
                  class Child(Base):
                      __tablename__ = "tbl_child"
                      __table_args__ = (
                          ForeignKeyConstraint(
                              ["parent_id1", "parent_id2"], ["tbl_parent.id1", "tbl_parent.id2"]
                          ),
                      )
                      id = Column(Integer, primary_key=True, autoincrement=False)
                      child_name = Column(String(50))
                      parent_id1 = Column(Integer)
                      parent_id2 = Column(Integer)
                  
                      parent = relationship(
                          "Parent",
                          foreign_keys="[Child.parent_id1, Child.parent_id2]",
                          back_populates="children",
                      )
                  
                      def __repr__(self):
                          return f"<Child(id={self.id}, child_name={self.child_name})>"
                  
                  
                  Base.metadata.create_all(engine)
                  
                  """ console output:
                  CREATE TABLE tbl_parent (
                      id1 INTEGER NOT NULL, 
                      id2 INTEGER NOT NULL, 
                      parent_name VARCHAR(50) NULL, 
                      PRIMARY KEY (id1, id2)
                  )
                  
                  
                  2020-04-30 07:52:43,771 INFO sqlalchemy.engine.Engine ()
                  2020-04-30 07:52:43,776 INFO sqlalchemy.engine.Engine COMMIT
                  2020-04-30 07:52:43,778 INFO sqlalchemy.engine.Engine 
                  CREATE TABLE tbl_child (
                      id INTEGER NOT NULL, 
                      child_name VARCHAR(50) NULL, 
                      parent_id1 INTEGER NULL, 
                      parent_id2 INTEGER NULL, 
                      PRIMARY KEY (id), 
                      FOREIGN KEY(parent_id1, parent_id2) REFERENCES tbl_parent (id1, id2)
                  )
                  
                  
                  2020-04-30 07:52:43,778 INFO sqlalchemy.engine.Engine ()
                  2020-04-30 07:52:43,802 INFO sqlalchemy.engine.Engine COMMIT
                  """
                  

                  参考:

                  https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/table_config.html#table-configuration

                  这篇关于SQLAlchemy ORM 不能使用复合外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:删除未级联到 sqlalchemy 中的表 下一篇:包括其他字段作为外键的选择,Django

                  相关文章

                • <i id='WHEtf'><tr id='WHEtf'><dt id='WHEtf'><q id='WHEtf'><span id='WHEtf'><b id='WHEtf'><form id='WHEtf'><ins id='WHEtf'></ins><ul id='WHEtf'></ul><sub id='WHEtf'></sub></form><legend id='WHEtf'></legend><bdo id='WHEtf'><pre id='WHEtf'><center id='WHEtf'></center></pre></bdo></b><th id='WHEtf'></th></span></q></dt></tr></i><div id='WHEtf'><tfoot id='WHEtf'></tfoot><dl id='WHEtf'><fieldset id='WHEtf'></fieldset></dl></div>

                  <small id='WHEtf'></small><noframes id='WHEtf'>

                  <tfoot id='WHEtf'></tfoot>

                    1. <legend id='WHEtf'><style id='WHEtf'><dir id='WHEtf'><q id='WHEtf'></q></dir></style></legend>

                      • <bdo id='WHEtf'></bdo><ul id='WHEtf'></ul>