【问题标题】:Remove a relation many-to-many (association object) on Sqlalchemy删除 Sqlalchemy 上的多对多关系(关联对象)
【发布时间】:2014-06-29 16:05:16
【问题描述】:

我遇到了一个 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 中。那么,我怎样才能删除这个关系呢?

【问题讨论】:

    标签: python flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    您可以覆盖__eq____ne____hash__,以便不同实例但具有相同值的实例进行比较和哈希相等。

    为此,我使用以下 mixin。只需在子类中覆盖 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())
    

    【讨论】:

      【解决方案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()
      

      【讨论】:

        猜你喜欢
        • 2015-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-24
        • 2013-11-13
        • 2016-04-11
        • 1970-01-01
        相关资源
        最近更新 更多