PostgreSQL支持提供的其他数据完整性约束 django.contrib.postgres.constraints
module.它们被添加到模型中 Meta.constraints
选择。
ExclusionConstraint
¶在数据库中创建排除约束。在内部,PostgreSQL使用索引实现排除约束。默认索引类型为 GiST .要使用它们,您需要激活 btree_gist extension 在PostgreSQL上。您可以使用 BtreeGistExtension
迁移操作。
如果您试图插入与现有行冲突的新行,则会出现 IntegrityError
被提出。同样,当更新与现有行冲突时。
期间检查排除约束。 model validation 。
name
¶看见 BaseConstraint.name
。
expressions
¶2-字节组的迭代对象。第一个元素是运算式或字符串。第二个元素是表示为字符串的SQL操作符。为了避免拼写错误,您可以使用 RangeOperators
它用字符串映射运算符。例如::
expressions = [
("timespan", RangeOperators.ADJACENT_TO),
(F("room"), RangeOperators.EQUAL),
]
对运营商的限制。
只有交换运算符可以用于排除约束。
这个 OpClass()
表达式可用于指定自定义 operator class 用于约束表达式。例如::
expressions = [
(OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
]
在上创建排除约束 circle
使用 circle_ops
。
index_type
¶约束的索引类型。接受的价值观是 GIST
或 SPGIST
.匹配不区分大小写。如果未提供,默认索引类型为 GIST
。
condition
¶A Q
对象,指定将约束限制到行子集的条件。例如, condition=Q(cancelled=False)
。
这些条件具有与 django.db.models.Index.condition
。
deferrable
¶设置此参数以创建可推迟的排除约束。接受的价值观是 Deferrable.DEFERRED
或 Deferrable.IMMEDIATE
。例如::
from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import RangeOperators
from django.db.models import Deferrable
ExclusionConstraint(
name="exclude_overlapping_deferred",
expressions=[
("timespan", RangeOperators.OVERLAPS),
],
deferrable=Deferrable.DEFERRED,
)
默认情况下,约束不会被推迟。直到事务结束才会强制执行延迟约束。每次命令后都会立即实施立即约束。
警告
推迟的排除限制可能会导致 performance penalty 。
include
¶要作为非键列包含在覆盖排除约束中的字段名称的列表或多元组。这允许将仅索引扫描用于仅选择包含字段的查询 (include
)并仅按索引字段过滤 (expressions
)。
include
GIST索引支持。PostgreSQL 14+还支持 include
用于SP-GIST索引。
violation_error_code
¶出现以下情况时使用的错误代码 ValidationError
是在过程中引发的 model validation 。默认为 None
。
violation_error_message
¶在以下情况下使用的错误消息 ValidationError
是在过程中引发的 model validation 。默认为 BaseConstraint.violation_error_message
。
以下示例限制同一房间中的重叠预订,而不考虑取消的预订::
from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
from django.db import models
from django.db.models import Q
class Room(models.Model):
number = models.IntegerField()
class Reservation(models.Model):
room = models.ForeignKey("Room", on_delete=models.CASCADE)
timespan = DateTimeRangeField()
cancelled = models.BooleanField(default=False)
class Meta:
constraints = [
ExclusionConstraint(
name="exclude_overlapping_reservations",
expressions=[
("timespan", RangeOperators.OVERLAPS),
("room", RangeOperators.EQUAL),
],
condition=Q(cancelled=False),
),
]
如果您的模型使用两个字段而不是原生的PostgreSQL范围类型定义范围,则应该编写一个使用等效函数的运算式(例如 TsTzRange()
),并使用该字段的分隔符。最常见的情况是,分隔符是 '[)'
,这意味着下限是包容性的,上限是排他性的。您可以使用 RangeBoundary
它为 range boundaries 。例如::
from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import (
DateTimeRangeField,
RangeBoundary,
RangeOperators,
)
from django.db import models
from django.db.models import Func, Q
class TsTzRange(Func):
function = "TSTZRANGE"
output_field = DateTimeRangeField()
class Reservation(models.Model):
room = models.ForeignKey("Room", on_delete=models.CASCADE)
start = models.DateTimeField()
end = models.DateTimeField()
cancelled = models.BooleanField(default=False)
class Meta:
constraints = [
ExclusionConstraint(
name="exclude_overlapping_reservations",
expressions=[
(
TsTzRange("start", "end", RangeBoundary()),
RangeOperators.OVERLAPS,
),
("room", RangeOperators.EQUAL),
],
condition=Q(cancelled=False),
),
]
7月 22, 2024