2017-08-29 62 views
1

我一直在使用flask和flask-sqlalchemy從MySQL數據庫中刪除多對多記錄。 似乎sqlalchemy試圖刪除關係表中的所有行,其中a的id與鏈接到b的相同。刪除多對多:Flask-Sqlalchemy試圖刪除具有特定ID的每一行

誤差(示例):

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

sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'ksiazka_wydawnictwo' expected to delete 552 row(s); Only 551 were matched. 

INFO sqlalchemy.engine.base.Engine DELETE FROM ksiazka_kategoria WHERE ksiazka_kategoria.ksiazka_id = %s AND ksiazka_kategoria.kategoria_id = %s 
2017-08-29 15:44:34,965 INFO sqlalchemy.engine.base.Engine ((166, 40), (167, 40), (168, 40), (169, 40), (170, 40), (171, 40), (172, 40), (173, 40) ... displaying 10 of 178 total bound parameter sets ... (1463, 19), (2046, 19)) 

關係表:

ksiazka_autor = db.Table('ksiazka_autor', 
     db.Column('autor_id', db.Integer, db.ForeignKey('autor.id')), 
     db.Column('ksiazka_id', db.Integer, db.ForeignKey('ksiazka.id')) 
    ) 
     ksiazka_wydawnictwo = db.Table('ksiazka_wydawnictwo', 
     db.Column('wydawnictwo_id', db.Integer, db.ForeignKey('wydawnictwo.id')), 
     db.Column('ksiazka_id', db.Integer, db.ForeignKey('ksiazka.id')) 
    ) 
    ksiazka_ilustrator = db.Table('ksiazka_ilustrator', 
     db.Column('ilustrator_id', db.Integer, db.ForeignKey('ilustrator.id')), 
     db.Column('ksiazka_id', db.Integer, db.ForeignKey('ksiazka.id')) 
    ) 
    ksiazka_kategoria = db.Table('ksiazka_kategoria', 
     db.Column('ksiazka_id', db.Integer, db.ForeignKey('ksiazka.id')), 
     db.Column('kategoria_id', db.Integer, db.ForeignKey('kategoria.id')) 
    ) 

及型號:

class Book(db.Model): 
    __tablename__ = 'ksiazka' 
    id = db.Column('id', db.Integer, primary_key=True) 
    [...] 

    authors = db.relationship('Author', secondary=ksiazka_autor, backref='authors', cascade="all", lazy='dynamic') 
    category = db.relationship('Category', secondary=ksiazka_kategoria, backref='category', cascade="all", lazy='dynamic') 
    publisher = db.relationship('Publisher', secondary=ksiazka_wydawnictwo, backref='publisher', cascade="all", lazy='dynamic') 
    artist = db.relationship('Artist', secondary=ksiazka_ilustrator, backref='artist', cascade="all", lazy='dynamic') 

class Author(db.Model): 
    __tablename__ = 'autor' 
    id = db.Column('id', db.Integer, primary_key=True) 
    [...] 
    books = db.relationship('Book', secondary=ksiazka_autor, backref=db.backref('books'), lazy='joined') 

class Category(db.Model): 
    __tablename__ = 'kategoria' 
    id = db.Column('id', db.Integer, primary_key=True) 
    [...] 
    cat_books = db.relationship('Book', secondary=ksiazka_kategoria, backref=db.backref('cat_books'), lazy='joined') 

class Publisher(db.Model): 
    __tablename__ = 'wydawnictwo' 
    id = db.Column('id', db.Integer, primary_key=True) 
    [...] 
    pub_books = db.relationship('Book', secondary=ksiazka_wydawnictwo, backref=db.backref('pub_books'), lazy='joined') 

class Artist(db.Model): 
    __tablename__ = 'ilustrator' 
    id = db.Column('id', db.Integer, primary_key=True) 
    [...] 
    art_books = db.relationship('Book', secondary=ksiazka_ilustrator, backref=db.backref('art_books'), lazy='joined') 

終於燒瓶代碼:

@app.route('/delete/book/<id>') 
def delete_book(id): 
    book = Book.query.filter_by(id=id).first() 
    db.session.delete(book) 
    db.session.commit() 
    return redirect('/home') 
+0

我認爲這是由於'''cascade option'''你在那裏,請參考文檔並明智地選擇刪除操作上的不同行爲。 http://docs.sqlalchemy.org/en/latest/orm/cascades.html – Gigapalmer

+0

那麼,最初我沒有「cascade =」all「」元素,而且我得到了同樣的錯誤。 –

回答

1

這是因爲你已經設置了,你想每個關係兩個獨立的關係。您有一個叫做Book.authors的關係和一個叫做Author.authors的後退參考,以及一個叫做Author.books的關係和一個叫做Book.books的後向參考。這是行不通的,因爲它們都在ksiazka_autor上運行,導致了你所看到的衝突。所有其他關係也一樣。

你想要什麼,而不是是使用back_populates選項:

class Book(db.Model): 
    ... 

    authors = db.relationship('Author', secondary=ksiazka_autor, back_populates='books', cascade="all", lazy='dynamic') 

class Author(db.Model): 
    ... 
    books = db.relationship('Book', secondary=ksiazka_autor, back_populates='authors', lazy='joined') 

手動刪除相關的實例,並承諾兩次是不正確的解決方案。

+0

感謝您的洞察!明天我會試一試。我還是SQLAlchemy的新手。 –