Spec-Zone.ru › Django 3.0

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

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

ExclusionConstraint

Новое в Django 3.0.
class ExclusionConstraint(*, name, expressions, index_type=None, condition=None)

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

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

name

ExclusionConstraint.name

Имя ограничения.

expressions

ExclusionConstraint.expressions

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

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

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

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

index_type

ExclusionConstraint.index_type

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

condition

ExclusionConstraint.condition

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

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

Примеры

В следующем примере ограничиваются перекрывающиеся бронирования в одном и том же зале, не учитывая отменённые бронирования:

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/3.0/ref/contrib/postgres/constraints/

Spec-Zone.ru

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