python - 有关系的删除行为

标签 python sqlalchemy

这不是真正的问题,我只是想了解一下。考虑以下代码:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()

class AB(Base):
    __tablename__= 'ab'
    id_a = Column(Integer, ForeignKey('a.id', ondelete='CASCADE'), primary_key=True)
    id_b = Column(Integer, ForeignKey('b.id', ondelete='CASCADE'), primary_key=True)
    rel = Column(Unicode)

class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)

class B(Base):
    __tablename__ = 'b'
    id = Column(Integer, primary_key=True)
    #1: doesn’t work try to set id_b to null
    rel_a = relationship('AB')
    # Works, but cascade='all' seems uneeded to me
    rel_a = relationship('AB', cascade='all')
    # Works 
    rel_a = relationship('AB', passive_deletes=True)

engine = create_engine('sqlite://', echo=True)

import logging
logger = logging.getLogger('sqlalchemy.engine.base.Engine')
logger.setLevel(logging.DEBUG)
handler = logger.handlers[0]
handler.setLevel(logging.DEBUG)
handler.setFormatter(logging.Formatter('%(levelname)s %(message)s', ''))

Base.metadata.create_all(engine)

sess = sessionmaker(engine)()

a1 = A()
b1 = B()
ab = AB()

sess.add_all([a1,b1])
sess.flush()

ab.id_a = a1.id
ab.id_b = b1.id
ab.rel = u'truite'
sess.add(ab)
sess.flush()
sess.delete(b1)
sess.flush()

B 中的相关记录被删除时,我希望从 AB 表中删除记录。 我尝试了 3 种类型的关系(检查 B 表):

  • 1:不起作用(AssertionError:Dependency rule tryed to blank-out primary key column 'ab.id_b' on instance ''),而如果尝试直接在数据库中删除它,约束是正确的使用,AB 的记录被删除。

  • 2:有效,我不明白为什么需要这样做,因为生成的数据库是相同的(您可以检查输出的差异)

  • 3:有效,数据库约束起作用。

除了 (3),我不明白为什么需要 (2),因为 ondelete='cascade' 已经设置,并且生成的 DB 是相同的。我的猜测是 (1),SQLAlchemy 有足够的信息来产生正确的行为。

我错过了什么吗?谢谢。

最佳答案

relationship 上的cascade 配置Session 操作的级联,例如Session.delete。它独立于您在数据库本身的外键约束上可能拥有的任何 ON X CASCADE 指令。

在你的例子中,cascade='all' 告诉 SQLAlchemy 从父对象 (AB) 到子对象。没有它,默认的操作模式是将 NULL 放入外键列并让引用的对象成为。

另一方面,passive_deletes=True 指示 SQLAlchemy 依靠数据库通过 ON DELETE CASCADE 指令清除已删除的对象。这可以防止 SQLAlchemy 自己发出 DELETE 查询,就像在 relationship(cascade=...) 情况下那样。

关于python - 有关系的删除行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11841586/

相关文章:

python - 如何对列表中彼此在 n 以内的元素进行分组

python - 将子查询与其父查询隔离

python - 在 pandas 中按组获取事件的连续出现次数

python - 循环尝试/排除

python - 在 osx 上安装 pycrypto 时出现问题

python - 如何在python中将字符串转换为json?

python - SQLAlchemy 混合表达式连接问题

sql - 查询和选择SQLAlchemy中的特定列

mysql - Sqlalchemy & Pylons : Adding new tables to a previously defined database?

Python SQLAlchemy 为什么我在 FK 上收到 NoReferencedTableError