SQLite布尔列,其中只有一个条目可以为真

时间:2020-05-22 09:16:36

标签: python sqlite peewee

我正在使用Python,Peewee和SQLite。

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

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

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

1 个答案:

答案 0 :(得分:0)

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

1st

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

第二

直接在数据库上创建一个DB trigger。您可以通过在项目的设置过程中运行一个init.sql文件或类似文件来完成此操作。此触发器将以与第一种方法的功能类似的方式工作,但现在通过BEFORE INSERT子句“触发”。与使用函数相比,这是一种更可取的方式,因为触发器以某种方式像钩子一样起作用。从重载者方面,可以通过signals extension处理。您可能想看看pre_save钩子。

3rd

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

最后,这是我对您询问的其他事项的评论:

  • 对于默认值,只需使用is_active = BooleanField(default=False)
  • 用于防止设置is_active字段。由于过去我没有处理过类似的事情,因此我可能没有为您提供最好的建议,但是我能想到的唯一方法是将属性/列设为其定义私有,这样您就可以只能通过数据库模型中的activate函数对其进行修改。另外,我可以考虑使用peewee hybrid attributes定义一个自定义访问器,该访问器在分配/设置时会引发错误。