在Sqlalchemy中移除多对多关系(关联对象)
我遇到了一个SqlAlchemy的问题。
我只是想删除一个关系。这个关系是通过一个关联对象建立的。
模型
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
我明白为什么不行,因为这个 Follower() 实例不在 u1.following 列表里。那么,我该怎么删除这个关系呢?
2 个回答
2
你也可以先查找这个对象,然后再从列表中删除它。
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()
2
你可以重写 __eq__
、__ne__
和 __hash__
这几个方法,这样即使两个对象不是同一个实例,但如果它们的值相同,它们在比较和哈希时也会被认为是相等的。
我使用下面这个混入类来实现这个功能。只需要在子类中重写 compare_value
方法,返回你想要比较的内容就可以了。
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())