I'm stuck with a SqlAlchemy problem.
I just want to delete an relation. This relation is made by an association object.
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
username = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
following = db.relationship('Follower', foreign_keys='Follower.user_id')
followed_by = db.relationship('Follower', foreign_keys='Follower.follow_user_id')
def __repr__(self):
return '<%s (%i)>' % (self.username, self.id)
class Follower(db.Model):
__tablename__ = 'followers'
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
follow_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
created_at = db.Column(db.DateTime, default=datetime.datetime.now)
user_followed = db.relationship("User", primaryjoin=(follow_user_id==User.id))
user = db.relationship("User", primaryjoin=(user_id==User.id))
def __repr__(self):
return '<%i %i>' % (self.user_id, self.follow_user_id)
u1 = # user 1
u2 = # user 2
...
f = Follower()
f.user_followed = u2
u1.following.append(f)
db.session.commit()
f = Follower()
f.user_followed = u2
u1.following.remove(f)
db.session.commit()
ValueError: list.remove(x): x not in list
I understand why it doesn't work, it's because this Follower() instance is not in the list u1.following. So, how can I delete this relation?
You can override __eq__
, __ne__
, and __hash__
so that instances that are not the same instance, but have the same values, compare and hash equal.
I use the following mixin for this purpose. Just override compare_value
in the subclass to return whatever should actually be compared.
from sqlalchemy import inspect
class EqMixin(object):
def compare_value(self):
"""Return a value or tuple of values to use for comparisons.
Return instance's primary key by default, which requires that it is persistent in the database.
Override this in subclasses to get other behavior.
"""
return inspect(self).identity
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self.compare_value() == other.compare_value()
def __ne__(self, other):
eq = self.__eq__(other)
if eq is NotImplemented:
return eq
return not eq
def __hash__(self):
return hash(self.__class__) ^ hash(self.compare_value())
One could also try querying for the object first and then delete it from the list.
follower_to_be_deleted = db.session.query(Follower).filter_by(user_id=u2.id).first()
u1.following.remove(follower_to_be_deleted)
db.session.commit()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With