【问题标题】:SQLite boolean column where only one entry can be trueSQLite 布尔列,其中只有一个条目可以为真
【发布时间】:2020-09-09 02:16:17
【问题描述】:

我正在使用 Python、Peewee 和 SQLite。

我需要建模一个条目表,其中最多一个条目可以处于“活动”状态。 所以有一个名为is_active的布尔列。

如何在 Peewee 中表达一个约束,以确保只有零或一行有is_active == True

此外,在创建条目期间,不应允许设置 is_active,最初应始终为 False。 将其设置为True 的唯一方法应该是通过模型上的activate() 方法首先停用剩余的条目。 如何在条目创建期间“隐藏”此属性?

【问题讨论】:

    标签: python sqlite peewee


    【解决方案1】:

    我可以在这里想到几种方法:

    第一个

    is_active 列定义CHECK 约束并创建用户定义的FUNCTION。新函数将返回数据库并查询表以验证来自SELECT COUNT(*) FROM table WHERE is_active = 1 的结果。如果是0activate,否则触发约束错误。请参阅1(Peewee 中的check 约束)和2(Peewee 中的用户定义函数)。

    第二次

    直接在数据库上创建DB trigger。您可以通过在项目设置期间运行的 init.sql 文件或类似文件来执行此操作。此触发器将以与第一种方法的功能类似的方式工作,但现在使用BEFORE INSERT 子句“触发”。这是比使用函数更受欢迎的方式,因为触发器在某种程度上就像钩子一样。在 peewee 方面,这可以通过signals extension 处理。你可能想看看pre_save 钩子。

    第三

    覆盖模型类中的save 方法,因此在再次调用super(Model, self).save(*args, **kwargs) 之前,请检查是否存在is_active = 1 所在的行。作为建议,我建议您仅覆盖在模型级别起作用的 save 函数,并避免覆盖其他 SQL 生成函数,例如 updateselect

    最后,我的 cmets 关于您询问的其他项目:

    • 对于默认值只需使用is_active = BooleanField(default=False)
    • 用于保护is_active 字段不被设置。我可能不会给你最好的建议,因为我过去没有处理过这样的事情,但我能想到的唯一方法是在其定义上将属性/列设为私有,这样你只能通过 activate 函数修改它,该函数将在您的 DB 模型中。或者,我可以考虑使用peewee hybrid attributes 定义一个自定义访问器,该访问器在分配/设置时会引发错误。

    【讨论】:

    • 非常感谢,这些方法看起来很有用。我暂时跳过了这个话题,但稍后会回到它,并在我得到它的工作时接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2018-10-28
    • 2017-09-17
    • 2021-05-15
    • 1970-01-01
    • 2013-11-03
    • 2022-11-30
    相关资源
    最近更新 更多