2017-04-05 21 views
1

私はFlask-SQLAlchemyを使用しています。私は、関連テーブルを介して関係を共有する2つのクラスを持っています。テーブルの1つの行を削除しようとしたとき。Flask SQLAlchemy多対多StaleDataError

tags = db.Table('tags', 
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), 
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id')) 
) 

class Post(db.Model): 
    __tablename__ = 'posts' 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(255)) 
    tags = db.relationship('Tag', secondary=tags, 
         backref=db.backref('posts', lazy='dynamic')) 

    def __init__(self, **kwargs): 
     super(Post, self).__init__(**kwargs) 

    def __repr__(self): 
     return '<title %r>' % self.title 


class Tag(db.Model): 
    __tablename__ = 'tag' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(120), unique=True) 

Anが、ここで私は削除するために実行コードは次のとおりです:ここで

sqlalchemy.orm.exc.StaleDataError 
StaleDataError: DELETE statement on table 'tags' expected to delete 1 row(s); Only 2 were matched. 

は私のモデルです:私は次のエラーを参照してください私は、ストライプダウンバージョンを試してみました

def remove_tag(tag_id): 
    tag = Tag.query.get(tag_id) 
    for post in tag.posts: 
     p = Post.query.get(post.id) 
     p.tags.remove(tag) 
db.session.delete(tag) 
db.session.commit() 

このコードの、このアプリの外で、スタンドアロンテスト、dbと環境。そして、それは期待どおりにタグと関連するテーブルの行を削除して動作します。

何可能であれば、私は、知っているしたいと思います:

  • にはどうすればStaleDataErrorの状況になりましたか?
  • .all()へのクエリで複数の用途が表示されない場合、なぜ複数の行に一致するのですか?
  • これを防ぐにはどうすればよいですか?

ご協力いただきありがとうございます。

ベスト、 エドワード

+0

私はあなたの例でいくつかのインデントを修正しましたが、 'remove_tag()'をそのまま残しましたが、何らかのエラーもあるようです。確認できますか? –

答えて

0

はひらめきを持っていました!

How did I get in the situation of a StaleDataError ?

私の編集の投稿ページをテストするとき、私は同じ投稿の多くのPOSTをデータベースに行いました。

Why does it match more than one row, when my query to .all() doesn't show multiple uses?

私のテストでは、関連テーブルに複数のエントリが作成されました。言い換えれば、私は(tag.id= 1, post.id=1)を何度も持っていました。

How can I prevent this from happening?

ユニーク制約を関連テーブルに追加して、DBへの複数のエントリを停止します。私は複数のエントリを停止するために私の見解でチェックを追加しました。

tags = db.Table(
    'tags', 
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), 
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id')), 
    db.UniqueConstraint('tag_id', 'post_id', name='UC_tag_id_post_id') 
) 

DBを移行します。

SQliteとAlembicを使用している場合、このエラーが発生する可能性が最も高くなります。「SQLiteダイアグラムの制約のALTERはサポートされていません」この問題の詳細はhereです。

要するに、これが開発用データベースの場合、DBを簡単に削除することができます。実稼働環境では、おそらくデータの移行を検討し、別のエンジンに切り替える必要があります。

関連する問題