• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Поля конкретной модели PostgreSQL

Все эти поля доступны из модуля django.contrib.postgres.fields.

Индексирование этих полей

Index и Field.db_index оба создают индекс B-дерева, что не особенно полезно при запросе сложных типов данных. Такие индексы, как GinIndex и GistIndex, подходят лучше, хотя выбор индекса зависит от используемых вами запросов. Как правило, GiST может быть хорошим выбором для полей range и HStoreField, а GIN может быть полезен для ArrayField.

МассивФилд

class ArrayField(base_field, size=None, **options)

Поле для хранения списков данных. Можно использовать большинство типов полей, и вы передаете другой экземпляр поля как base_field. Вы также можете указать size. ArrayField может быть вложенным для хранения многомерных массивов.

Если вы задаете поле default, убедитесь, что это вызываемый объект, такой как list (для пустого значения по умолчанию) или вызываемый объект, который возвращает список (например, функция). Неправильное использование default=[] создает изменяемое значение по умолчанию, которое используется всеми экземплярами ArrayField.

base_field

Это обязательный аргумент.

Указывает базовый тип данных и поведение массива. Это должен быть экземпляр подкласса Field. Например, это может быть IntegerField или CharField. Разрешено большинство типов полей, за исключением тех, которые обрабатывают реляционные данные (ForeignKey, OneToOneField и ManyToManyField) и файловых полей (FileField и ImageField).

Поля массива можно вкладывать друг в друга — вы можете указать экземпляр ArrayField в качестве base_field. Например:

from django.contrib.postgres.fields import ArrayField
from django.db import models


class ChessBoard(models.Model):
    board = ArrayField(
        ArrayField(
            models.CharField(max_length=10, blank=True),
            size=8,
        ),
        size=8,
    )

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

size

Это необязательный аргумент.

Если оно передано, массив будет иметь указанный максимальный размер. Это будет передано в базу данных, хотя PostgreSQL в настоящее время не применяет это ограничение.

Примечание

При вложении ArrayField, независимо от того, используете ли вы параметр size или нет, PostgreSQL требует, чтобы массивы были прямоугольными:

from django.contrib.postgres.fields import ArrayField
from django.db import models


class Board(models.Model):
    pieces = ArrayField(ArrayField(models.IntegerField()))


# Valid
Board(
    pieces=[
        [2, 3],
        [2, 1],
    ]
)

# Not valid
Board(
    pieces=[
        [2, 3],
        [2],
    ]
)

Если требуются нестандартные формы, то базовое поле должно быть обнуляемым, а значения дополняться «Нет».

Запрос ArrayField

Существует ряд пользовательских поисков и преобразований для ArrayField. Мы будем использовать следующий пример модели:

from django.contrib.postgres.fields import ArrayField
from django.db import models


class Post(models.Model):
    name = models.CharField(max_length=200)
    tags = ArrayField(models.CharField(max_length=200), blank=True)

    def __str__(self):
        return self.name

contains

Поиск contains переопределяется в ArrayField. Возвращенными объектами будут те, в которых переданные значения являются подмножеством данных. Он использует оператор SQL @>. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__contains=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contains=["django"])
<QuerySet [<Post: First post>, <Post: Third post>]>

>>> Post.objects.filter(tags__contains=["django", "thoughts"])
<QuerySet [<Post: First post>]>

contained_by

Это обратный поиску contains — возвращаемые объекты будут теми, в которых данные представляют собой подмножество переданных значений. Он использует оператор SQL <@. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__contained_by=["thoughts", "django"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contained_by=["thoughts", "django", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>

перекрытие

Возвращает объекты, в которых данные разделяют любые результаты с переданными значениями. Использует оператор SQL &&. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts", "tutorial"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__overlap=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__overlap=["thoughts", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>

>>> Post.objects.filter(tags__overlap=Post.objects.values_list("tags"))
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>

лен

Возвращает длину массива. После этого доступны поиски для IntegerField. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])

>>> Post.objects.filter(tags__len=1)
<QuerySet [<Post: Second post>]>

Индексные преобразования

Индекс преобразует индекс в массив. Можно использовать любое неотрицательное целое число. Ошибок не возникает, если он превышает size массива. После преобразования доступны поиски из base_field. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])

>>> Post.objects.filter(tags__0="thoughts")
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__1__iexact="Django")
<QuerySet [<Post: First post>]>

>>> Post.objects.filter(tags__276="javascript")
<QuerySet []>

Примечание

PostgreSQL использует индексацию с отсчетом от 1 для полей массива при написании необработанного SQL. Однако эти индексы и индексы, используемые в slices, используют индексацию, отсчитываемую от 0, чтобы быть совместимыми с Python.

Срезные преобразования

Преобразования среза берут часть массива. Можно использовать любые два неотрицательных целых числа, разделенных одним подчеркиванием. Поиски, доступные после преобразования, не изменяются. Например:

>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["django", "python", "thoughts"])

>>> Post.objects.filter(tags__0_1=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__0_2__contains=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

Примечание

PostgreSQL использует индексацию с отсчетом от 1 для полей массива при написании необработанного SQL. Однако эти фрагменты и те, которые используются в indexes, используют индексацию, отсчитываемую от 0, чтобы быть совместимыми с Python.

Многомерные массивы с индексами и срезами

PostgreSQL имеет довольно эзотерическое поведение при использовании индексов и срезов в многомерных массивах. Всегда можно использовать индексы для доступа к окончательным базовым данным, но большинство других фрагментов ведут себя странно на уровне базы данных и не могут поддерживаться Django логически и последовательно.

HStoreField

class HStoreField(**options)

Поле для хранения пар ключ-значение. Используемый тип данных Python — «dict». Ключи должны быть строками, а значения могут быть либо строками, либо значениями NULL («None» в Python).

Чтобы использовать это поле, вам необходимо:

  1. Добавьте 'django.contrib.postgres' в настройки:INSTALLED_APPS.

  2. Настройте расширение hstore в PostgreSQL.

Вы увидите ошибку типа «невозможно адаптировать тип «dict», если пропустите первый шаг, или «тип «hstore» не существует», если пропустите второй.

Примечание

В некоторых случаях может быть полезно потребовать или ограничить ключи, действительные для данного поля. Это можно сделать с помощью KeysValidator.

Запрос HStoreField

Помимо возможности запроса по ключу, для HStoreField доступен ряд пользовательских поисков.

Мы будем использовать следующий пример модели:

from django.contrib.postgres.fields import HStoreField
from django.db import models


class Dog(models.Model):
    name = models.CharField(max_length=200)
    data = HStoreField()

    def __str__(self):
        return self.name

Ключевые запросы

Для запроса на основе заданного ключа вы можете использовать этот ключ в качестве имени поиска:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie"})

>>> Dog.objects.filter(data__breed="collie")
<QuerySet [<Dog: Meg>]>

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

>>> Dog.objects.filter(data__breed__contains="l")
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>

или используйте выражения F() для аннотации значения ключа. Например:

>>> from django.db.models import F
>>> rufus = Dog.objects.annotate(breed=F("data__breed"))[0]
>>> rufus.breed
'labrador'

Если ключ, который вы хотите запросить, конфликтует с именем другого поиска, вам нужно вместо этого использовать поиск hstorefield.contains.

Примечание

Ключевые преобразования также могут быть связаны с помощью: contains, icontains, endswith, iendswith, iexact, regex, iregex, startswith, и istartswith поиска.

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

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

contains

Поиск contains переопределяется в HStoreField. Возвращаемые объекты — это те объекты, в поле которых содержатся все заданные пары ключ-значение. Он использует оператор SQL @>. Например:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__contains={"owner": "Bob"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>

>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>

contained_by

Это обратный поиску contains — возвращаемые объекты будут теми, в которых пары ключ-значение объекта являются подмножеством пар в переданном значении. Он использует оператор SQL <@. Например:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
<QuerySet [<Dog: Meg>, <Dog: Fred>]>

>>> Dog.objects.filter(data__contained_by={"breed": "collie"})
<QuerySet [<Dog: Fred>]>

has_key

Возвращает объекты, в данных которых находится заданный ключ. Использует оператор SQL ?. Например:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__has_key="owner")
<QuerySet [<Dog: Meg>]>

has_any_keys

Возвращает объекты, в данных которых присутствует любой из заданных ключей. Использует оператор SQL ?|. Например:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>

has_keys

Возвращает объекты, в данных которых присутствуют все заданные ключи. Использует оператор SQL ?&. Например:

>>> Dog.objects.create(name="Rufus", data={})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__has_keys=["breed", "owner"])
<QuerySet [<Dog: Meg>]>

ключи

Возвращает объекты, где массив ключей имеет заданное значение. Обратите внимание, что надежность порядка не гарантируется, поэтому это преобразование в основном полезно использовать в сочетании с поиском по ArrayField. Использует функцию SQL keys(). Например:

>>> Dog.objects.create(name="Rufus", data={"toy": "bone"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__keys__overlap=["breed", "toy"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>

ценности

Возвращает объекты, в которых массив значений является заданным значением. Обратите внимание, что надежность порядка не гарантируется, поэтому это преобразование в основном полезно использовать в сочетании с поиском по ArrayField. Использует функцию SQL avals(). Например:

>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__values__contains=["collie"])
<QuerySet [<Dog: Meg>]>

Поля диапазона

Существует пять типов полей диапазона, соответствующих встроенным типам диапазонов в PostgreSQL. Эти поля используются для хранения диапазона значений; например, временные метки начала и окончания события или диапазон возрастов, для которого подходит занятие.

Все поля диапазона преобразуются в psycopg Range объекты в Python, но также принимают кортежи в качестве входных данных, если информация о границах не требуется. По умолчанию нижняя граница включена, а верхняя граница исключена, то есть [) (подробную информацию о различных границах`_ см. в документации PostgreSQL). Границы по умолчанию можно изменить для полей недискретного диапазона (:class:`.DateTimeRangeField` и :class:`.DecimalRangeField`) с помощью аргумента ``default_bounds.

PostgreSQL нормализует диапазон без точек на пустой диапазон.

Диапазон с равными значениями, указанными для включенной нижней границы и исключенной верхней границы, например Range(datetime.date(2005, 6, 21), datetime.date(2005, 6, 21)) или [4, 4), не имеет точек. PostgreSQL нормализует значение до пустого при сохранении в базе данных, а исходные связанные значения будут потеряны. Подробности смотрите в документации PostgreSQL <https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO>`_.

IntegerRangeField

class IntegerRangeField(**options)

Хранит диапазон целых чисел. На основе IntegerField. Представлено int4range в базе данных и django.db.backends.postgresql.psycopg_any.NumericRange в Python.

Независимо от границ, указанных при сохранении данных, PostgreSQL всегда возвращает диапазон в канонической форме, который включает нижнюю границу и исключает верхнюю границу, то есть [).

BigIntegerRangeField

class BigIntegerRangeField(**options)

Хранит диапазон больших целых чисел. На основе BigIntegerField. Представлено int8range в базе данных и django.db.backends.postgresql.psycopg_any.NumericRange в Python.

Независимо от границ, указанных при сохранении данных, PostgreSQL всегда возвращает диапазон в канонической форме, который включает нижнюю границу и исключает верхнюю границу, то есть [).

Десятичноеполедиапазона

class DecimalRangeField(default_bounds='[)', **options)

Хранит диапазон значений с плавающей запятой. На основе DecimalField. Представлено диапазоном чисел в базе данных и django.db.backends.postgresql.psycopg_any.NumericRange в Python.

default_bounds

Необязательный. Значение границ для входных данных списков и кортежей. По умолчанию нижняя граница включена, а верхняя граница исключена, то есть [) (подробную информацию о различных границах`_ см. в документации PostgreSQL). ``default_bounds не используется для входных данных django.db.backends.postgresql.psycopg_any.NumericRange.

DateTimeRangeField

class DateTimeRangeField(default_bounds='[)', **options)

Хранит диапазон временных меток. На основе DateTimeField. Представлено tstzrange в базе данных и django.db.backends.postgresql.psycopg_any.DateTimeTZRange в Python.

default_bounds

Необязательный. Значение границ для входных данных списков и кортежей. По умолчанию нижняя граница включена, а верхняя граница исключена, то есть [) (подробную информацию о различных границах`_ см. в документации PostgreSQL). ``default_bounds не используется для входных данных django.db.backends.postgresql.psycopg_any.DateTimeTZRange.

ДатаРангеФилд

class DateRangeField(**options)

Хранит диапазон дат. На основе DateField. Представлено диапазоном дат в базе данных и django.db.backends.postgresql.psycopg_any.DateRange в Python.

Независимо от границ, указанных при сохранении данных, PostgreSQL всегда возвращает диапазон в канонической форме, который включает нижнюю границу и исключает верхнюю границу, то есть [).

Запрос полей диапазона

Существует ряд пользовательских поисков и преобразований для полей диапазона. Они доступны во всех вышеуказанных полях, но мы будем использовать следующий пример модели:

from django.contrib.postgres.fields import IntegerRangeField
from django.db import models


class Event(models.Model):
    name = models.CharField(max_length=200)
    ages = IntegerRangeField()
    start = models.DateTimeField()

    def __str__(self):
        return self.name

Мы также будем использовать следующие примеры объектов:

>>> import datetime
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Event.objects.create(name="Soft play", ages=(0, 10), start=now)
>>> Event.objects.create(
...     name="Pub trip", ages=(21, None), start=now - datetime.timedelta(days=1)
... )

и NumericRange:

>>> from django.db.backends.postgresql.psycopg_any import NumericRange

Функции сдерживания

Как и в случае с другими полями PostgreSQL, здесь есть три стандартных оператора включения: contains, contained_by и overlap, использующие операторы SQL @>, <@ и && соответственно.

contains
>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
<QuerySet [<Event: Soft play>]>
contained_by
>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
<QuerySet [<Event: Soft play>]>

Поиск contained_by также доступен для типов полей, не входящих в диапазон: SmallIntegerField, IntegerField, BigIntegerField, DecimalField, FloatField, DateField и DateTimeField. Например:

>>> from django.db.backends.postgresql.psycopg_any import DateTimeTZRange
>>> Event.objects.filter(
...     start__contained_by=DateTimeTZRange(
...         timezone.now() - datetime.timedelta(hours=1),
...         timezone.now() + datetime.timedelta(hours=1),
...     ),
... )
<QuerySet [<Event: Soft play>]>
перекрытие
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
<QuerySet [<Event: Soft play>]>

Функции сравнения

Поля диапазона поддерживают стандартные поиски: lt, gt, lte и gte. Это не особенно полезно — сначала сравниваются нижние границы, а затем только при необходимости верхние границы. Эта стратегия также используется для заказа по полю диапазона. Лучше использовать конкретные операторы сравнения диапазонов.

полностью_lt

Возвращаемые диапазоны строго меньше переданного диапазона. Другими словами, все точки в возвращаемом диапазоне меньше всех точек в переданном диапазоне.

>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
<QuerySet [<Event: Soft play>]>
полностью_gt

Возвращаемые диапазоны строго превышают переданный диапазон. Другими словами, все точки в возвращаемом диапазоне больше, чем все точки в переданном диапазоне.

>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
<QuerySet [<Event: Pub trip>]>
not_lt

Возвращаемые диапазоны не содержат точек меньше переданного диапазона, то есть нижняя граница возвращаемого диапазона является как минимум нижней границей переданного диапазона.

>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
not_gt

Возвращаемые диапазоны не содержат точек, превышающих переданный диапазон, то есть верхняя граница возвращаемого диапазона не превышает верхней границы переданного диапазона.

>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
<QuerySet [<Event: Soft play>]>
adjacent_to

Возвращенные диапазоны имеют общую границу с переданным диапазоном.

>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>

Запрос с использованием границ

Поля диапазона поддерживают несколько дополнительных поисков.

startswith

Возвращенные объекты имеют заданную нижнюю границу. Может быть привязан к допустимым поискам для базового поля.

>>> Event.objects.filter(ages__startswith=21)
<QuerySet [<Event: Pub trip>]>
endswith

Возвращенные объекты имеют заданную верхнюю границу. Может быть привязан к допустимым поискам для базового поля.

>>> Event.objects.filter(ages__endswith=10)
<QuerySet [<Event: Soft play>]>
пустой

Возвращаемые объекты представляют собой пустые диапазоны. Может быть привязан к допустимому поиску для BooleanField.

>>> Event.objects.filter(ages__isempty=True)
<QuerySet []>
lower_inc

Возвращает объекты, имеющие включающие или исключающие нижние границы, в зависимости от переданного логического значения. Может быть привязан к допустимому поиску для BooleanField.

>>> Event.objects.filter(ages__lower_inc=True)
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
lower_inf

Возвращает объекты, имеющие неограниченную (бесконечную) или ограниченную нижнюю границу, в зависимости от переданного логического значения. Может быть привязан к допустимому поиску для BooleanField.

>>> Event.objects.filter(ages__lower_inf=True)
<QuerySet []>
upper_inc

Возвращает объекты, которые имеют инклюзивные или исключительные верхние границы, в зависимости от переданного логического значения. Может быть привязан к допустимому поиску для BooleanField.

>>> Event.objects.filter(ages__upper_inc=True)
<QuerySet []>
upper_inf

Возвращает объекты, имеющие неограниченную (бесконечную) или ограниченную верхнюю границу, в зависимости от переданного логического значения. Может быть привязан к допустимому поиску для BooleanField.

>>> Event.objects.filter(ages__upper_inf=True)
<QuerySet [<Event: Pub trip>]>

Определение собственных типов диапазонов

PostgreSQL позволяет определять собственные типы диапазонов. Реализации модели и поля формы Django используют базовые классы, представленные ниже, а psycopg предоставляет register_range(), позволяющий использовать пользовательские типы диапазонов.

class RangeField(**options)

Базовый класс для полей модельного ряда.

base_field

Используемый класс поля модели.

range_type

Тип диапазона, который нужно использовать.

form_field

Используемый класс поля формы. Должен быть подклассом django.contrib.postgres.forms.BaseRangeField.

class django.contrib.postgres.forms.BaseRangeField

Базовый класс для полей диапазона формы.

base_field

Поле формы, которое нужно использовать.

range_type

Тип диапазона, который нужно использовать.

Операторы диапазона

class RangeOperators

PostgreSQL предоставляет набор операторов SQL, которые можно использовать вместе с типами данных диапазона (полную информацию об операторах диапазона см. в документации PostgreSQL <https://www.postgresql.org/docs/current/functions-range.html#RANGE-OPERATORS-TABLE>`_). Этот класс задуман как удобный способ избежать опечаток. Имена операторов перекрываются с именами соответствующих поисков.

class RangeOperators:
    EQUAL = "="
    NOT_EQUAL = "<>"
    CONTAINS = "@>"
    CONTAINED_BY = "<@"
    OVERLAPS = "&&"
    FULLY_LT = "<<"
    FULLY_GT = ">>"
    NOT_LT = "&>"
    NOT_GT = "&<"
    ADJACENT_TO = "-|-"

Выражения RangeBoundary()

class RangeBoundary(inclusive_lower=True, inclusive_upper=False)
inclusive_lower

Если True (по умолчанию), нижняя граница является включающей '[', в противном случае она является эксклюзивной '('.

inclusive_upper

Если False (по умолчанию), верхняя граница является исключающей ')', в противном случае она включает ']'.

Выражение RangeBoundary() представляет границы диапазона. Его можно использовать с пользовательскими функциями диапазона, которые ожидают границы, например, для определения ExclusionConstraint. Подробную информацию см. в документации PostgreSQL <https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-INCLUSIVITY>`_.

Back to Top