SQLAlchemy:直接从一对多关系中删除对象,而不使用session.delete()

时间:2014-04-27 13:21:17

标签: python mysql session sqlalchemy one-to-many

我有以下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不更新post_id的NULL值的注释(由于列上的非空约束而不允许),但是删除注释?我知道我可以做session.delete(comment),但由于我不需要明确地向会话添加评论,所以我没有看到为什么我必须明确地从会话中删除它。

我找到了几个用于级联删除相关对象的解决方案,但由于我从未对会话发出任何明确的删除(帖子仍在那里),我认为这不适用。

修改:我调整了示例以包含帖子中删除的级联。现在它可以执行session.delete(post)并删除所有注释。但我只是想自动删除我从关系中删除的评论,而不是删除包含所有评论的整个帖子。

TL; DR :当我从一对多关系的关系列表中删除条目时,如何告诉SQLAlchemy发出删除语句而不是更新语句?

2 个答案:

答案 0 :(得分:10)

阅读文档的Configuring delete/delete-orphan Cascade部分以获取更多信息,但基本上您需要delete-orphan以及cascade的{​​{1}}选项:

relationship

答案 1 :(得分:0)

我不是SQLAlchemy用户,但我认为你应该使用ondelete选项

    post_id = Column(Integer, ForeignKey(Post.id, ondelete="CASCADE"), nullable=False)

参见,Mysql 5.6手册13.6.44,FOREIGN KEY约束

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部分:定义外键 - > ON UPDATE和ON DELETE