Taceor
Taceor

Reputation: 61

Flask SQLAlchemy Many to Many Delete Element

My Flask site has Suggestions and Users.

class Suggestion(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_nickname = db.Column(db.Integer, db.ForeignKey('user.nickname'))
    voters = db.relationship('User', secondary=votes, lazy='dynamic')

class User(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    suggestions = db.relationship('Suggestion', backref='user', lazy='dynamic')
    votes = db.relationship('Suggestion', secondary=votes, lazy='dynamic') 

I have set up a many to many relationship between the two as such.

votes = db.Table('votes',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('suggestion_id', db.Integer, db.ForeignKey('suggestion.id'))
)

When I try to delete a Suggestion inside my views.py I get an error.

The View:

@app.route('/_delete_suggestion', methods=['GET', 'POST'])
    def delete_suggestion():
    user_nickname = request.form.get('user_nickname')
    user = User.query.filter_by(nickname=user_nickname).first()
    sugg_id = request.form.get('sugg_id')
    sugg = Suggestion.query.filter_by(id=sugg_id).first()
    if user.is_special:
        db.session.delete(sugg)
        db.session.commit()
    else:
        flash('You are not cool enough to do that!')
        return redirect(url_for('index'))
    return

@app.route('/_upvote', methods=['GET', 'POST'])
    def upvote():
    user_nickname = request.form.get('user_nickname')
    user = User.query.filter_by(nickname=user_nickname).first()
    sugg_id = request.form.get('sugg_id')
    sugg = Suggestion.query.filter_by(id=sugg_id).first()
    if sugg.voters.filter_by(nickname=user_nickname).first() is not None:
        print("ERR", file=sys.stderr)
    else:
        print("VOTED", file=sys.stderr)
        sugg.score += 1
        sugg.voters.append(user)
        user.votes.append(sugg)
        db.session.add(sugg)
        db.session.add(user)
        db.session.commit()
    return

The Error:

StaleDataError: DELETE statement on table 'votes' expected to delete 2 row(s); Only 4 were matched.

What I Know:

What I Have Tried:

What am I missing? This is driving me up a wall!

EDIT: Inside a python interpreter, I tried to the following.

s = Suggestion.query.first()
for v in s.voters.all():
    s.voters.remove(v)
s.voters.all()

This then crashed and produced the same StaleDataError.

Upvotes: 2

Views: 1417

Answers (1)

Taceor
Taceor

Reputation: 61

I figured it out! I was adding into the Many to Many array twice inside the _upvote route.

Original _upvote snippet:

print("VOTED", file=sys.stderr)
sugg.score += 1
sugg.voters.append(user)
user.votes.append(sugg)
db.session.add(sugg)
db.session.add(user)
db.session.commit()

Fixed _upvote snippet:

print("VOTED", file=sys.stderr)
sugg.score += 1
sugg.voters.append(user)
db.session.add(sugg)
db.session.commit()

Upvotes: 2

Related Questions