在SQLAlchemy Flask中删除项目列表

6

我希望以一种优雅的方式使用Flask和SQLAlchemy从列表中删除项目。在我的情况下,我想从数据库中删除旧项目(即小于某个特定时间的项目被视为旧项目)。

这是我的Python模型对象:

class ItemModel(db.Model):
    __tablename__ = 'items'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    time = db.Column(db.Integer)

现在,我尝试使用以下filter_by查询来删除项目:
def delete_from_db(self):
    db.session.query('items').filter_by(self.time <= epoch_time).delete()
    db.session.commit()

我得到了以下错误:

filter_by()需要1个定位参数,但提供了2个

如果我尝试使用filter函数而不是filter_by函数,我也会收到一个错误:

   def delete_from_db(self):
        db.session.query('items').filter(self.time <= epoch_time).delete()
        db.session.commit()

sqlalchemy.exc.InvalidRequestError: 此操作要求只指定一个表或实体作为目标。

最终,我决定回到基础并使用SQL代码,这样可以解决问题,但我认为这并不太优雅:

def delete_from_db(self):
    from sqlalchemy.sql import text
    cmd = 'delete from items where time <= :time'
    db.engine.execute(text(cmd), time = epoch_time)
    db.session.commit()

有没有更优雅的方式使用Flask和SQLAchlemy来完成这个任务?

1
关于filter和filter_by之间的区别:https://dev59.com/k3I95IYBdhLWcg3w2Rvz - Ilja Everilä
1
后一种异常是查询中没有可选择项的结果。过滤条件看起来就像普通的 Python 对象,在 Python 中会求值为 True 或 False。'query('items')' 创建一个带有单个实体的查询,字面上的 SQL 是 'items',不含删除操作的话类似于 SELECT items。这种情况下异常信息有点误导。 - Ilja Everilä
嗨,我想做类似的事情,但我想让epoch_time成为一个新月的开始,而不是一个固定的deltatime。我该如何实现这一点? - Reactive_learner
1个回答

14

如果您希望从模型中管理此内容,那么使用类方法应该可以解决:

@classmethod
def delete_from_db(cls):
    cls.query.filter(cls.time <= epoch_time).delete()
    db.session.commit()

或者说,也许更干净一些,使用静态方法:

@staticmethod
def delete_from_db():
    ItemModel.query.filter(ItemModel.time <= epoch_time).delete()
    db.session.commit()

2
请注意,使用db.session.delete(ItemModel.query.filter(ItemModel.time <= epoch_time).first())级联删除,而此方法不会进行级联删除。在经过大量搜索和试错后,这个链接帮助了我。 - Khaled Hamed
1
感谢@KhaledHamed的评论,确实值得注意!这个答案也很相关:https://dev59.com/yWIk5IYBdhLWcg3wdeDY#19245058 - PRMoureu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接