我正在使用Python,Peewee和SQLite。
我需要对一个条目表进行建模,其中最多一个条目可以处于“活动”状态。
因此,有一个名为is_active
的布尔列。
我如何在Peewee中表达一个约束,以确保只有零或一行包含is_active == True
?
此外,在创建条目期间,不应该设置is_active
,最初应始终为False
。
将其设置为True
的唯一方法应该是通过首先停用其余条目的模型上的activate()
方法。
如何在条目创建过程中“隐藏”该属性?
答案 0 :(得分:0)
我可以在这里想到几种方法:
为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
钩子。
在模型类中重写save
方法,因此在再次调用super(Model, self).save(*args, **kwargs)
之前,请检查is_active = 1
处是否不存在任何行。作为建议,我建议您仅覆盖在模型级别起作用的save
函数,并避免覆盖其他SQL生成函数,例如update
或select
。
最后,这是我对您询问的其他事项的评论:
is_active = BooleanField(default=False)
is_active
字段。由于过去我没有处理过类似的事情,因此我可能没有为您提供最好的建议,但是我能想到的唯一方法是将属性/列设为其定义私有,这样您就可以只能通过数据库模型中的activate
函数对其进行修改。另外,我可以考虑使用peewee hybrid attributes
定义一个自定义访问器,该访问器在分配/设置时会引发错误。