SQLAlchemy级联删除(可能是会话混淆)

时间:2014-03-09 15:12:15

标签: python sqlite sqlalchemy

我正在尝试在删除父级时将删除级联到子级中。根据这个问题SQLAlchemy: cascade delete我将cascade="all, delete-orphan"选项添加到了孩子的backref中。这似乎在某种程度上起作用。事实上孩子们已经从数据库中删除了(通过SQLlite数据库浏览器确认),但孩子们仍然可以看到“python side”:

CODE:

class Product(Base):
    __tablename__ = 'products'
    id = Column(Integer, primary_key=True)
    product_name = Column(String(250), unique=True)
    vendor_id = Column(Integer, ForeignKey('vendors.id'), nullable=False)

    vendor = relationship('Vendor', backref = backref('products', order_by=id, cascade="all, delete-orphan"))

    def __init__(self, product_name, vendor_id):
        self.product_name = product_name
        self.vendor_id = vendor_id

    def __repr__(self):
        return '<Product: %r Product ID: %r Vendor ID: %r>' % (self.product_name, self.id, self.vendor_id)


class Module(Base):
    __tablename__ = 'modules'
    id = Column(Integer, primary_key=True)
    module_name = Column(String(250), unique=True)
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)

    product = relationship('Product', backref = backref('modules', order_by=id, cascade="all, delete-orphan"))

    def __init__(self, module_name, product_id):
        self.module_name = module_name
        self.product_id = product_id


    def __repr__(self):
        return '<Module: %r Module ID: %r Product ID: %r>' % (self.module_name, self.id ,self.product_id)

TEST:

msg('Module Tests')
Product2Mod1 = Module('Product2Mod1',1)
Product2Mod2 = Module('Product2Mod2',1)
Product1Mod1 = Module('Product1Mod1',2)
Product1Mod2 = Module('Product1Mod2',2)
Product1Mod3 = Module('Product1Mod3',2)
db_session.add(Product2Mod1)
db_session.add(Product2Mod2)
db_session.add(Product1Mod1)
db_session.add(Product1Mod2)
db_session.add(Product1Mod3)
db_session.commit()
msg("Product2Mod1 Product:")
print Product2Mod1.product

msg('delete tests')

print "Query to show all products: \n"
print Product.query.all()

print "\nQuery to show all modules: \n"
print Module.query.all()

print "\ndeleting product 1: db_session.delete(Product1) --> db_session.commit()"
db_session.delete(Product1)
db_session.commit()
db_session.flush()

print "\nQuery to check for changes with products and modules (THIS IS CORRECT):\n"
print Product.query.all()
print Module.query.all()

print "\nThe modules below belong to the deleted product, they should have disappeared (But they did not, THIS IS INCORRECT):"
print Product1Mod1
print Product1Mod2
print Product1Mod3

1 个答案:

答案 0 :(得分:2)

实际上,SQLAlchemy在这里表现正常。要理解它,你必须离开SQLAlchemy一步之遥。您告诉库删除其后端的内容。但是,您仍然可以引用您自己创建的实例并仅提供它。以这个人为的例子:

some_obj = MyClass()
backend_storage.store(some_obj)
backend_storage.delete(some_obj)

您现在在本地空间some_obj会发生什么?这个库应该删除你的变量吗?

SQLAlchemy以这种方式运行:它知道这些对象已经消失,因此询问它们将不再返回它们。但是,你仍然在本地使用它们,并且它们已经在那里存在,所以只要你重新注入它们,它们就会在内存中存在。

另外一件事:如果您自己创建这些对象或者库返回它们并不重要。他们现在是“你的”,现在外部代码应该搞乱。例如:

some_obj = backend_storage.load_one(MyClass)  # load the first object of MyClass
backend_storage.delete(some_obj)

与上述相同:some_obj 你的。如果需要,您甚至可以立即重新添加它,后端无需关心。