【问题标题】:SQLAlchemy foreign key constraintSQLAlchemy 外键约束
【发布时间】:2018-03-05 05:39:42
【问题描述】:

我在插入新记录时无法理解 ForeignKey 约束如何与 SQLAlchemy 一起工作。我有一个父表,它有两个子表,每个子表都是 one_2_many 关系。我的底层数据库是 Oracle,这是我的表的简化模型:

class ProductCategory(db.Model):
  __tablename__ = 'productcategory'
  product_category_id = Column(Integer, Sequence('productcategory_seq', primary_key=True)
  label = Column(String)
  products = relation('Product', backref='product_category')
  printers = relation('Printer', backref='product_category')

class Product(db.Model):
  __tablename__ = 'product'
  product_id = Column(Integer, Sequence('product_seq'), primary_key=True)
  product_category_id = Column(Integer, ForeignKey('productcategory.product_category_id')
  name = Column(String)

class Printer(db.Model):
  __tablename__ = 'printer'
  printer_id = Column(Integer, Sequence('printer_seq'),
  product_category_id = Column(Integer, ForeignKey('product_category.product_category_id')
  name = Column(String)

这是引发 (cx_Oracle.IntegrityError) ORA-02291: 完整性约束 (EASTLAB.SYS_C0049050) 违反 - 父键未找到异常的 Python 代码的简化示例

try:
  product_category = ProductCategory(label='some_category')
  db.session.add(product_category)
    
  # iterate over the products in the category
  for product in products:
    new_product = Product(
      product_category=product_category,
      name=product.name
    )
    db.session.add(new_product)

  # iterate over the printers in the category
  for printer in printers:
    new_printer = Printer(
      product_category=product_category,
      name=printer.name
    )
    db.session.add(new_printer)

  # commit before exiting context manager
  db.session.commit()
except:
  db.session.rollback()

在执行 db.session.commit() 代码时引发异常。我不确定为什么会引发异常,我在上面所做的似乎是我在各种在线帖子中看到的模式。有趣的是,如果我注释掉添加打印机子项的代码,这可以正常工作。我很困惑。

我可以尝试什么来解决这个问题?

【问题讨论】:

    标签: python oracle sqlalchemy


    【解决方案1】:

    Printer 上的外键 product_category_id 引用的是 'product_category.product_category_id' 而不是 'productcategory.product_category_id'

    使用以下对我有用的测试:

    class ProductCategory(Base):
        __tablename__ = 'productcategory'
        product_category_id = Column(Integer, Sequence('productcategory_seq'), primary_key=True)
        label = Column(String)
        products = relation('Product', backref='product_category')
        printers = relation('Printer', backref='product_category')
    
    
    class Product(Base):
        __tablename__ = 'product'
        product_id = Column(Integer, Sequence('product_seq'), primary_key=True)
        product_category_id = Column(Integer, ForeignKey('productcategory.product_category_id'))
        name = Column(String)
    
    
    class Printer(Base):
        __tablename__ = 'printer'
        printer_id = Column(Integer, Sequence('printer_seq'), primary_key=True)
        product_category_id = Column(Integer, ForeignKey('productcategory.product_category_id'))
        name = Column(String)
    
    
    Base.metadata.create_all(engine)
    
    Session = sessionmaker(bind=engine)
    session = Session()
    
    product_category = ProductCategory(label='some_category')
    session.add(product_category)
    
    product_names = ["a", "b", "c"]
    
    # iterate over the products in the category
    for product in product_names:
        new_product = Product(
            product_category=product_category,
            name=product
        )
        session.add(new_product)
    
    printer_names = ["a", "b", "c"]
    
    # iterate over the printers in the category
    for printer in printer_names:
        new_printer = Printer(
            product_category=product_category,
            name=printer
        )
        session.add(new_printer)
    
    # commit before exiting context manager
    session.commit()
    

    与您的示例略有不同,因为您在将示例添加到您的问题时省略了一些右括号,并且我稍微更改了它获取 PrintersProducts 示例的方式。

    【讨论】:

      猜你喜欢
      • 2011-08-30
      • 1970-01-01
      • 2021-12-04
      • 2018-02-19
      • 2022-12-21
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      相关资源
      最近更新 更多