SQLAlchemy:如何在一对多关系中直接删除对象而不使用session.delete()
我有一个这样的SQLAlchemy设置:
Base = declarative_base()
class Post(Base):
__tablename__ = 'post'
id = Column(Integer, primary_key=True)
title = Column(String(30))
comments = relationship('Comment', cascade='all')
class Comment(Base):
__tablename__ = 'comment'
id = Column(Integer, primary_key=True)
post_id = Column(Integer, ForeignKey(Post.id, ondelete='CASCADE'), nullable=False)
text = Column(Text)
通过这个设置,我可以创建帖子对象,并且这些帖子可以有多个评论。我想在不提到会话的情况下处理评论的创建和删除。给帖子添加评论是没问题的:
post = Post(title='some post')
comment = Comment(text='some comment')
post.comments.append(comment)
我的会话处理器只知道帖子,所以它会执行 session.add(post)
,这样评论就会自动添加到会话中,并在下次执行 session.commit()
时与数据库同步。但是,删除评论就不一样了。我想通过简单地执行:
post.comments.remove(comment)
来删除评论,但在下次执行 session.commit()
时会出现以下错误:
sqlalchemy.exc.OperationalError: (OperationalError) (1048, "Column 'post_id' cannot be null") 'UPDATE comment SET post_id=%s WHERE comment.id = %s' (None, 1L)
我该如何告诉SQLAlchemy在删除评论时,不要用 NULL
值更新评论的post_id(因为这个列不允许为NULL),而是直接删除评论呢?我知道我可以执行 session.delete(comment)
,但因为我在添加评论时并没有明确地将其添加到会话中,所以我不明白为什么在删除时也要明确地从会话中删除它。
我找到了一些关于级联删除相关对象的解决方案,但因为我从未对会话进行过明确的删除操作(帖子仍然存在),所以我觉得这些方案不适用。
编辑:我调整了示例,包含了从帖子级联删除的功能。现在执行 session.delete(post)
时,所有评论都会被删除。但我只想自动删除我从关系中移除的评论,而不是删除整个帖子和所有评论。
总结:我该如何告诉SQLAlchemy在我从一对多关系的关系列表中移除一个条目时,发出删除语句而不是更新语句?
2 个回答
我不是SQLAlchemy的用户,但我觉得你应该使用ondelete这个选项。
post_id = Column(Integer, ForeignKey(Post.id, ondelete="CASCADE"), nullable=False)
你看,Mysql 5.6手册第13.6.44节,讲的是外键约束。
SET NULL: Delete or update the row from the parent table, and set the foreign key column or columns in the child table to NULL. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
CASCADE: Delete or update the row from the parent table, and automatically delete or update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between two tables, do not define several ON UPDATE CASCADE clauses that act on the same column in the parent table or in the child table.
还有,http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html 这一部分:定义外键 -> 更新和删除时的处理。
想了解更多信息,可以查看文档中关于配置删除/孤儿删除级联的部分。简单来说,你在relationship
的cascade
选项中也需要加上delete-orphan
。
class Post(Base):
# ...
comments = relationship('Comment', cascade="all, delete-orphan")