Spec-Zone.ru › Django 1.8

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

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

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.db import models
from django.contrib.postgres.fields import ArrayField

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

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

Запрос к ArrayField

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

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

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

    def __str__(self):  # __unicode__ on Python 2
        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'])
[<Post: First post>, <Post: Second post>]

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

>>> Post.objects.filter(tags__contains=['django', 'thoughts'])
[<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'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial'])
[<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'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
[<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)
[<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')
[<Post: First post>, <Post: Second post>]

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

>>> Post.objects.filter(tags__276='javascript')
[]

Примечание

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'])
[<Post: First post>, <Post: Second post>]

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

Примечание

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

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

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

Индексирование ArrayField

В настоящее время использование db_index создаст индекс btree. Это не особенно помогает в запросах. Более полезный индекс — индекс GIN, который следует создать с помощью операции RunSQL.

HStoreField

class HStoreField(**options) [source]

Поле для хранения сопоставлений строк со строками. Используемый тип данных Python — dict.

Для использования этого поля необходимо:

  1. Добавить 'django.contrib.postgres' в ваш INSTALLED_APPS.
  2. Настройте расширение hstore в PostgreSQL перед первой операцией CreateModel или AddField добавив миграцию с операцией HStoreExtension. Например:

    from django.contrib.postgres.operations import HStoreExtension
    
    class Migration(migrations.Migration):
        ...
    
        operations = [
            HStoreExtension(),
            ...
        ]
    

    Для создания расширения требуется пользователь базы данных с привилегиями суперпользователя. Если пользователь базы данных Django не имеет привилегий суперпользователя, вам нужно создать расширение вне миграций Django с пользователем, имеющим соответствующие привилегии. В этом случае подключитесь к базе данных Django и выполните запрос CREATE EXTENSION IF NOT EXISTS hstore;

Вы увидите ошибку, подобную 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):  # __unicode__ on Python 2
        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')
[<Dog: Meg>]

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

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

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

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

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

contains

Поиск contains переопределен для HStoreField. Возвращаются объекты, где заданные dict пары ключ-значение полностью содержатся в поле. Используется оператор 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'})
[<Dog: Rufus>, <Dog: Meg>]

>>> Dog.objects.filter(data__contains={'breed': 'collie'})
[<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'})
[<Dog: Meg>, <Dog: Fred>]

>>> Dog.objects.filter(data__contained_by={'breed': 'collie'})
[<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')
[<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'])
[<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'])
[<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'])
[<Dog: Meg>]

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

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

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

IntegerRangeField

class IntegerRangeField(**options) [source]

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

BigIntegerRangeField

class BigIntegerRangeField(**options) [source]

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

FloatRangeField

class FloatRangeField(**options) [source]

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

DateTimeRangeField

class DateTimeRangeField(**options) [source]

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

DateRangeField

class DateRangeField(**options) [source]

Хранит диапазон дат. Основан на DateField. Представлен как daterange в базе данных и как DateRange в Python.

Запрос по полям диапазона

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

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

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

    def __str__(self):  # __unicode__ on Python 2
        return self.name

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

>>> Event.objects.create(name='Soft play', ages=(0, 10))
>>> Event.objects.create(name='Pub trip', ages=(21, None))

и NumericRange:

>>> from psycopg2.extras import NumericRange

Функции сопоставления

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

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

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

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

fully_lt

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

>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
[<Event: Soft play>]
fully_gt

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

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

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

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

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

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

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

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

Запрос по границам

Доступны три преобразования для использования в запросах. Можно извлечь нижнюю или верхнюю границу или выполнить запрос на основе пустоты.

startswith

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

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

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

>>> Event.objects.filter(ages__endswith=10)
[<Event: Soft play>]
isempty

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

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

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

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/1.8/ref/contrib/postgres/fields/

Spec-Zone.ru

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