Spec-Zone.ru › Django 5.1

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

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

ExclusionConstraint

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. То же самое относится и к обновлению, если оно конфликтует с существующей строкой.

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

name

ExclusionConstraint.name

См. BaseConstraint.name.

expressions

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.

index_type

ExclusionConstraint.index_type

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

condition

ExclusionConstraint.condition

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

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

deferrable

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

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

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

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

include

ExclusionConstraint.include

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

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

violation_error_code

Добавлено в Django 5.0.
ExclusionConstraint.violation_error_code

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

violation_error_message

Сообщение об ошибке, используемое при поднятии 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.1/ref/contrib/postgres/constraints/

Spec-Zone.ru

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