Spec-Zone.ru › Django 2.1

Поля моделей, специфичные для PostgreSQL

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

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

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

ArrayField

class ArrayField(base_field, size=None, **options) [source]

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

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

base_field

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

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

Возможна вложенность полей массивов — вы можете указать экземпляр 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],
])

Если требуются непрямоугольные формы, то подлежащее поле должно быть сделано nullable, а значения заполнены None.

Запросы к 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>]>

overlap

Возвращает объекты, где данные имеют какие-либо результаты с переданными значениями. Используется оператор 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__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>]>

len

Возвращает длину массива. Доступные впоследствии поисковые запросы — те, которые доступны для 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 логичным и последовательным образом.

CIText поля

class CIText(**options) [source]

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

Чтобы использовать citext, используйте операцию CITextExtension, чтобы настроить расширение citext в PostgreSQL перед первой миграцией CreateModel.

Предоставляются несколько полей, которые используют этот миксин:

class CICharField(**options) [source]
class CIEmailField(**options) [source]
class CITextField(**options) [source]

Эти поля являются подклассами CharField, EmailField и TextField соответственно.

max_length не будут проверены в базе данных, так как citext ведет себя подобно типу text PostgreSQL.

HStoreField

class HStoreField(**options) [source]

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

Для использования этого поля вам нужно:

  1. Добавить 'django.contrib.postgres' в ваш INSTALLED_APPS.
  2. Настроить расширение hstore в PostgreSQL.

Вы увидите ошибку, похожую на can't adapt type 'dict', если вы пропустите первый шаг, или type "hstore" does not exist если вы пропустите второй.

Примечание

В некоторых случаях может быть полезно потребовать или ограничить допустимые ключи для данного поля. Это можно сделать с помощью 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>]>

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

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

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

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

keys

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

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

values

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

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

JSONField

class JSONField(encoder=None, **options) [source]

Поле для хранения данных, закодированных в формате JSON. В Python данные представлены в родном формате Python: словари, списки, строки, числа, булевы значения и None.

encoder

Дополнительный класс кодирования JSON для сериализации типов данных, не поддерживаемых стандартным сериализатором JSON (datetime, uuid, и т. д.). Например, вы можете использовать класс DjangoJSONEncoder или любой другой подкласс json.JSONEncoder.

При получении значения из базы данных оно будет в формате, выбранном пользовательским кодером (чаще всего, это строка), поэтому вам необходимо предпринять дополнительные шаги для преобразования значения обратно в исходный тип данных (Model.from_db() и Field.from_db_value() — два возможных крючка для этой цели). Ваша десериализация может потребовать учета того, что вы не можете быть уверены в типе входных данных. Например, вы рискуете получить datetime, который на самом деле был строкой, совпадающей по формату с типом данных, выбранным для datetime.

Если вы устанавливаете default для поля, убедитесь, что это вызываемый объект, например, dict (для пустого значения по умолчанию) или вызываемый объект, возвращающий словарь (например, функция). Неправильное использование default={} создаёт изменяемый по умолчанию параметр, который делится между всеми экземплярами JSONField.

Примечание

PostgreSQL имеет два собственных типа данных на основе JSON: json и jsonb. Основное различие между ними заключается в том, как они хранятся и как к ним можно обращаться. Поле json PostgreSQL хранит исходное строковое представление JSON и должно декодироваться на лету при запросе по ключам. Поле jsonb хранится на основе фактической структуры JSON, что позволяет индексировать. Компромисс — небольшая дополнительная стоимость при записи в поле jsonb. JSONField использует jsonb.

Запросы к полю JSONField

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

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

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

    def __str__(self):
        return self.name

Поиск по ключу, индексу и пути

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

>>> Dog.objects.create(name='Rufus', data={
...     'breed': 'labrador',
...     'owner': {
...         'name': 'Bob',
...         'other_pets': [{
...             'name': 'Fishy',
...         }],
...     },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': None})

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

Несколько ключей могут быть объединены для поиска по пути:

>>> Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>

Если ключ является целым числом, он будет интерпретирован как поиск по индексу в массиве:

>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>

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

Если используется только один ключ или индекс, используется оператор SQL ->. Если используется несколько операторов, используется оператор #>.

Для поиска null в данных JSON используйте None в качестве значения.

>>> Dog.objects.filter(data__owner=None)
<QuerySet [<Dog: Meg>]>

Для поиска отсутствующих ключей используйте тип поиска isnull.

>>> Dog.objects.create(name='Shep', data={'breed': 'collie'})
>>> Dog.objects.filter(data__owner__isnull=True)
<QuerySet [<Dog: Shep>]>
Изменено в Django 2.1:

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

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

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

Операции включения и с ключами

JSONField использует типы поиска, связанные с включением и ключами, аналогично HStoreField.

  • contains (принимает любой JSON, а не только словарь строк)
  • contained_by (принимает любой JSON, а не только словарь строк)
  • has_key
  • has_any_keys
  • has_keys

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

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

Все поля диапазонов преобразуются в объекты psycopg2 Range в Python, но также принимают кортежи в качестве входных данных, если информация о границах не требуется. По умолчанию используется нижняя граница, включенная, верхняя граница, исключённая; то есть [).

IntegerRangeField

class IntegerRangeField(**options) [source]

Хранит диапазон целых чисел. Основан на IntegerField. Представлен в базе данных как int4range и как NumericRange в Python.

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

BigIntegerRangeField

class BigIntegerRangeField(**options) [source]

Хранит диапазон больших целых чисел. Основан на BigIntegerField. Представлен в базе данных как int8range и как NumericRange в Python.

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

FloatRangeField

class FloatRangeField(**options) [source]

Хранит диапазон значений с плавающей точкой. Основан на FloatField. Представлен в базе данных как numrange и как NumericRange в Python.

DateTimeRangeField

class DateTimeRangeField(**options) [source]

Хранит диапазон временных меток. Основан на DateTimeField. Представлен в базе данных как tstzrange и как DateTimeTZRange в Python.

DateRangeField

class DateRangeField(**options) [source]

Хранит диапазон дат. Основан на DateField. Представлен в базе данных как daterange и как 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 psycopg2.extras 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 также доступен для типов полей без диапазона: IntegerField, BigIntegerField, FloatField, DateField и DateTimeField. Например:

>>> from psycopg2.extras 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>]>
overlap
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
<QuerySet [<Event: Soft play>]>

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

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

fully_lt

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

>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
<QuerySet [<Event: Soft play>]>
fully_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>]>
isempty

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

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

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

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

class RangeField(**options) [source]

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

base_field

Класс поля модели для использования.

range_type

Тип диапазона psycopg2 для использования.

form_field

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

class django.contrib.postgres.forms.BaseRangeField

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

base_field

Поле формы для использования.

range_type

Тип диапазона psycopg2 для использования.

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

Spec-Zone.ru

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