【问题标题】:How to create an exclude constraint with a daterange using sqlalchemy如何使用 sqlalchemy 创建具有日期范围的排除约束
【发布时间】:2020-06-18 23:31:01
【问题描述】:

我知道只使用原始 sql,我可以像这样添加排除约束:

ADD CONSTRAINT unique_daterange_constraint
EXCLUDE  USING gist
( foo WITH =, 
  daterange(start_date, end_date, '[]') WITH &&
);

但是,我需要能够对 sqlalchemy 做同样的事情。我目前在表 args 中拥有的(不起作用)是:

    __table_args__ = (
    postgresql.ExcludeConstraint(
        ("foo", "="),
        (DateRange("start_date", "end_date", bounds="[]"), "&&"),
        name="unique_daterange_constraint",
        using="gist",
    ),
)

DateRange 是从 psycopg2.extras 导入的,据我了解,这是如何复制上面 sql 中使用的 postgres daterange 类型。

我的堆栈跟踪,在尝试创建 alembic 迁移文件时告诉我 daterange 部分有误

sqlalchemy.exc.ArgumentError: SQL expression object expected, got object of type <class 'psycopg2._range.DateRange'> instead

我知道我可以处理此问题的一种潜在方法(因为它确实需要一个我放置 DateRange 的列)是创建一个 daterange 列和一个触发器,该触发器在插入或更新时使用 start 填充我的 daterange 列和结束日期,但感觉我不应该这样做。看来,如果我可以使用 sql 中的现有列简单地定义一个日期范围,我应该也可以使用 sqlalchemy。

有什么方法可以按照我想要的方式实现吗?

【问题讨论】:

    标签: python postgresql sqlalchemy


    【解决方案1】:

    由于需要一个 SQL 表达式对象,因此请提供一个。假设您已将列属性命名为与其 DB 对应项相同,并在列定义后定义 Table 参数:

    __table_args__ = (
        postgresql.ExcludeConstraint(
            ("foo", "="),
            (func.daterange(start_date, end_date, "[]"), "&&"),
            name="unique_daterange_constraint",
            using="gist",
        ),
    )
    

    【讨论】:

    • 非常感谢。为了代码库的一致性,我最终使用了这种方法,但在类定义之后使用 MyTable.__table__.append_constraint(),而不是将 table_args 向下倾倒在底部以处理使用之前定义的列名问题.
    • 作为记录,当提供 bounds 参数时它会吓坏。看来我必须只保留两个列名,然后在 alembic 迁移中的 op.execute 中正确写入边界(因为无论如何约束都不会自动添加到迁移中)
    • 它是怎么吓到的? “使用前”问题的另一个解决方案是使用轻量级 sqlalchemy.column() 来生成列引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多