web-dev-qa-db-ja.com

SQLAlchemy:session.delete()を使用せずに、1対多の関係からオブジェクトを直接削除します

次の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)
_

これにより、コメントと1対多の関係を持つ投稿オブジェクトを作成できます。セッションを参照せずに投稿のコメントの作成と削除を処理したい。投稿にコメントを追加すると、問題なく機能します。

_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)
_

Post_idのNULL値(列にnull以外の制約があるため許可されていません)でコメントを更新せず、代わりにコメントを削除するようにSQLAlchemyに指示するにはどうすればよいですか? session.delete(comment)を実行できることは知っていますが、セッションにコメントを明示的に追加する必要がなかったため、セッションからコメントを明示的に削除する必要がある理由がわかりません。

関連するオブジェクトへの削除をカスケードするためのいくつかの解決策を見つけましたが、セッションに明示的な削除を発行することは決してないので(投稿はまだそこにあります)、それは当てはまらないと思います。

編集:投稿からの削除のカスケードを含めるように例を調整しました。これで、session.delete(post)を実行できるようになり、すべてのコメントが削除されます。ただし、関係から削除したコメントを自動的に削除し、すべてのコメントを含む投稿全体を削除したくないだけです。

TL; DR:1対多の関係の関係リストからエントリを削除するときに、更新ステートメントではなく削除ステートメントを発行するようにSQLAlchemyに指示するにはどうすればよいですか?

14
Varicus

詳細については、ドキュメントの delete/delete-Orphan Cascadeの構成 セクションをお読みください。ただし、基本的には、cascaderelationshipオプションにもdelete-Orphanが必要です。 :

class Post(Base):
    # ...
    comments = relationship('Comment', cascade="all, delete-Orphan")
14
van

私はSQLAlchemyユーザーではありませんが、ondeleteオプションを使用する必要があると思います

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

Mysql 5.6マニュアル13.6.44、外部キーの制約を参照してください。

 SET NULL:親テーブルから行を削除または更新し、子テーブルの1つまたは複数の外部キー列をNULLに設定します。
 ON DELETE SETNULL句とONUPDATE SETNULL句はどちらもサポートされています。
 CASCADE:親テーブルから行を削除または更新し、子テーブルの一致する行を自動的に削除または更新します。
 ONDELETECASCADEとONUPDATECASCADEの両方がサポートされています。 2つのテーブル間で、親テーブルまたは子テーブルの同じ列に作用する複数のON UPDATE 
 CASCADE句を定義しないでください。

そして http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html セクション:外部キーの定義->更新時と削除時

0
maliubiao