Spec-Zone.ru › Django 5.2

Ограничения базы данных, специфичные для PostgreSQL

PostgreSQL поддерживает дополнительные ограничения целостности данных, доступные из модуля django.contrib.postgres.constraints. Они добавляются в модели в параметре Meta.constraints.

Ограничение исключения

class ExclusionConstraint(*, name, expressions, index_type=None, condition=None, deferrable=None, include=None, violation_error_code=None, violation_error_message=None) [source]

Создаёт ограничение исключения в базе данных. Внутренне PostgreSQL реализует ограничения исключения с использованием индексов. По умолчанию тип индекса — GiST. Для их использования необходимо активировать расширение btree_gist в PostgreSQL. Вы можете установить его с помощью операции миграции BtreeGistExtension.

Если вы попытаетесь вставить новую строку, которая конфликтует с существующей строкой, будет возбуждено исключение IntegrityError. Аналогично, при обновлении, если обновление конфликтует с существующей строкой.

Ограничения исключения проверяются во время валидации модели.

Имя

ExclusionConstraint.name

См. BaseConstraint.name.

Выражения

ExclusionConstraint.expressions

Итерируемый объект кортежей из 2-х элементов. Первый элемент — это выражение или строка. Второй элемент — это оператор SQL, представленный строкой. Чтобы избежать ошибок, вы можете использовать RangeOperators, который сопоставляет операторы со строками. Например:

expressions = [
    ("timespan", RangeOperators.ADJACENT_TO),
    (F("room"), RangeOperators.EQUAL),
]

Ограничения на операторы.

В ограничениях исключения можно использовать только коммутативные операторы.

Выражение OpClass() может быть использовано для указания пользовательского класса операторов для выражений ограничения. Например:

expressions = [
    (OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
]

создаёт ограничение исключения на circle с помощью circle_ops.

Тип индекса

ExclusionConstraint.index_type

Тип индекса ограничения. Допустимые значения — GIST или SPGIST. Проверка нечувствительна к регистру. Если не указано, по умолчанию используется тип индекса GIST.

Условие

ExclusionConstraint.condition

Объект Q, который определяет условие для ограничения до подмножества строк. Например, condition=Q(cancelled=False).

Эти условия имеют те же ограничения базы данных, что и django.db.models.Index.condition.

Отложенное выполнение

ExclusionConstraint.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,
)

По умолчанию ограничения не откладываются. Отложенное ограничение не будет принудительно выполняться до конца транзакции. Немедленное ограничение будет принудительно выполняться немедленно после каждой команды.

Предупреждение

Отложенные ограничения исключения могут привести к снижению производительности.

Включать

ExclusionConstraint.include

Список или кортеж имён полей, которые должны быть включены в охватывающее ограничение исключения в качестве неключевых столбцов. Это позволяет использовать индекс-только сканирование для запросов, которые выбирают только включённые поля (include) и фильтруют только по индексированным полям (expressions).

include поддерживается для индексов GiST. PostgreSQL 14+ также поддерживает include для индексов SP-GiST.

Код ошибки нарушения

ExclusionConstraint.violation_error_code

Код ошибки, используемый при возбуждении ValidationError во время валидации модели. По умолчанию равен None.

Сообщение об ошибке нарушения

Сообщение об ошибке, используемое при возбуждении ValidationError во время валидации модели. По умолчанию равно 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, который предоставляет отображение выражений для границ диапазонов. Например:

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),
            ),
        ]

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/ref/contrib/postgres/constraints/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API