sqlalchemy,使用检查约束

时间:2016-02-25 01:25:44

标签: python flask sqlalchemy

我刚开始使用sqlalchemy,我想在我的一个列上设置检查约束。我有一个名为startTimeendTime的列,我想确保endTime > startTime

from sqlalchemy import Column, Integer, String, ForeignKey, Date
import models.Base

class Session(Base):
    __tablename__ = 'sessions'

    sid = Column(Integer, primary_key=True)
    uid = Column(Integer, ForeignKey('users.uid'), nullable=False)
    startTime= Column(Date, nullable=False)

    #probably won't work
    endTime = Column(Date, CheckConstraint('endTime > startTime'), nullable=False)

3 个答案:

答案 0 :(得分:4)

这是一个有效的语法,但在MySQL中(我假设您使用的是MySQL?),这将被忽略。来自sqla docs:

>检查约束可以命名或未命名,可以使用CheckConstraint构造在Column或Table级别创建。检查约束的文本直接传递到数据库,因此存在有限的“数据库独立”行为。列级检查约束通常应仅引用它们所在的列,而表级约束可引用表中的任何列。 请注意,某些数据库不主动支持检查约束,例如MySQL。

您可以创建一个触发器,但是然后您将业务逻辑放到数据库层。我会编写一个app-level构造函数检查。

答案 1 :(得分:0)

除了MySQL不支持检查约束的事实外,我认为问题是您试图在列级检查约束中引用多个列。

假设您使用了另一个数据库,则需要在表级别定义约束,如下所示:

from sqlalchemy import Column, Integer, String, ForeignKey, Date
import models.Base

class Session(Base):
    __tablename__ = 'sessions'
    __table_args__ = (
        CheckConstraint('endTime > startTime'),
    )

    sid = Column(Integer, primary_key=True)
    uid = Column(Integer, ForeignKey('users.uid'), nullable=False)
    startTime= Column(Date, nullable=False)

    endTime = Column(Date, nullable=False)

答案 2 :(得分:0)

创建检查约束的另一种方法是使用SQLAlchemy的event.listen事件API。

在用例中,我想在模型上创建列检查,其中列不能为负数。

event.listen(target, identifier, func)

在这种情况下,目标是我的模型(“发布”)和我的列(“支持”)。在这种情况下,标识符为“设置”。在这种情况下,该函数是在我的模型中创建的静态方法。所以看起来像这样:

event.listen(Post.upvotes, "set", Post.before_set_upvotes)

我的功能如下:

@staticmethod
def before_set_upvotes(target, value, oldvalue, initiator):
    if value < 0:
        raise ValueError('Upvotes cannot be a negative value')

目标参数是“ Post.upvotes”,value是我们将列属性设置为的值。注意:在event.listen中使用的函数需要4个参数,我不确定为什么这样,如果有人有原因请发表评论。没有4个参数(仅将目标值和值作为args),我得到了错误TypeError: before_set_upvotes() takes 2 positional arguments but 4 were given

现在,您可以通过运行一个试图为该列设置并提交负数的函数来进行测试。将会产生值错误,从而创建我们需要的约束。