# Поля сериализатора

## Поля сериализатора

> Каждое поле в классе Form отвечает не только за проверку данных, но и за их "очистку" — приведение их к единообразному формату.
>
> — [Django documentation](https://docs.djangoproject.com/en/stable/ref/forms/api/#django.forms.Form.cleaned_data)

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

***

**Примечание:** Поля сериализатора объявляются в `fields.py`, но по соглашению вы должны импортировать их с помощью `from rest_framework import serializers` и обращаться к полям как `serializers.<FieldName>`.

***

### Основные аргументы

Каждый конструктор класса поля сериализатора принимает как минимум эти аргументы. Некоторые классы `Field` принимают дополнительные, специфические для поля аргументы, но следующие должны приниматься всегда:

#### `read_only`

Поля, доступные только для чтения, включаются в выходные данные API, но не должны включаться во входные данные при операциях создания или обновления. Любые поля `read_only`, по ошибке включенные во входные данные сериализатора, будут проигнорированы.

Установите значение `True`, чтобы гарантировать, что поле используется при сериализации представления, но не используется при создании или обновлении экземпляра во время десериализации.

По умолчанию `False`.

#### `write_only`

Установите значение `True`, чтобы поле могло использоваться при обновлении или создании экземпляра, но не включалось при сериализации представления.

По умолчанию `False`.

#### `required`

Обычно ошибка возникает, если поле не предоставлено во время десериализации. Установите значение `False`, если это поле не обязательно должно присутствовать при десериализации.

Установка этого значения в `False` также позволяет не выводить атрибут объекта или ключ словаря при сериализации экземпляра. Если ключ не присутствует, он просто не будет включен в выходное представление.

По умолчанию имеет значение `True`. При использовании [Model Serializer](https://ilyachch.gitbook.io/django-rest-framework-russian-documentation/overview/serializers#modelserializer) значение по умолчанию будет `False`, если вы указали `blank=True` или `default` или `null=True` для вашего поля в вашей `Model`.

#### `default`

Если установлено, это значение по умолчанию, которое будет использоваться для поля, если значение не передано. Если значение не задано, то по умолчанию атрибут вообще не заполняется.

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

Может быть задана как функция или другой вызываемый объект, в этом случае значение будет выполняться каждый раз при его использовании. При вызове оно не получает никаких аргументов. Если вызываемая функция имеет атрибут `requires_context = True`, то поле сериализатора будет передано в качестве аргумента.

Например:

```python
class CurrentUserDefault:
    """
    May be applied as a `default=...` value on a serializer field.
    Returns the current user.
    """
    requires_context = True

    def __call__(self, serializer_field):
        return serializer_field.context['request'].user
```

При сериализации экземпляра будет использоваться значение по умолчанию, если атрибут объекта или ключ словаря не присутствует в экземпляре.

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

#### `allow_null`

Обычно, если в поле сериализатора передается `None`, возникает ошибка. Установите этот именованный аргумент в `True`, если `None` должно считаться допустимым значением.

Обратите внимание, что без явного указания `default` установка этого аргумента в `True` подразумевает `default` значение `null` для вывода сериализации, но не подразумевает значение по умолчанию для десериализации ввода.

По умолчанию `False`.

#### `source`

Имя атрибута, который будет использоваться для заполнения поля. Может быть методом, который принимает только аргумент `self`, например `URLField(source='get_absolute_url')`, или может использовать точечную нотацию для обхода атрибутов, например `EmailField(source='user.email')`.

При сериализации полей с точечной нотацией может потребоваться предоставить значение `default`, если какой-либо объект отсутствует или пуст при обходе атрибута. Остерегайтесь возможных проблем n+1 при использовании атрибута source, если вы обращаетесь к реляционной модели orm. Например:

```python
class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField(source="user.email")
```

В этом случае объект пользователя должен быть извлечен из базы данных, если он не был предварительно извлечен. Если это нежелательно, убедитесь, что вы используете методы `prefetch_related` и `select_related` соответствующим образом. Более подробную информацию об этих методах можно найти в [документации django](https://docs.djangoproject.com/en/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related).

Значение `source='*'` имеет особое значение и используется для указания на то, что в поле должен быть передан весь объект. Это может быть полезно для создания вложенных представлений или для полей, которым требуется доступ к полному объекту для определения выходного представления.

По умолчанию используется имя поля.

#### `validators`

Список функций валидаторов, которые должны быть применены к вводимому полю и которые либо выдают ошибку валидации, либо просто возвращаются. Функции валидатора обычно должны вызывать `serializers.ValidationError`, но встроенный в Django `ValidationError` также поддерживается для совместимости с валидаторами, определенными в кодовой базе Django или в сторонних пакетах Django.

#### `error_messages`

Словарь кодов ошибок и сообщений об ошибках.

#### `label`

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

#### `help_text`

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

#### `initial`

Значение, которое должно использоваться для предварительного заполнения значений полей HTML-формы. Вы можете передать ему вызываемый объект, как и в случае с любым обычным полем Django `Field`:

```python
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
    day = serializers.DateField(initial=datetime.date.today)
```

#### `style`

Словарь пар ключ-значение, которые можно использовать для управления тем, как рендереры должны отображать поле.

Двумя примерами здесь являются `'input_type'` и `'base_template'`:

```python
# Use <input type="password"> for the input.
password = serializers.CharField(
    style={'input_type': 'password'}
)

# Use a radio input instead of a select input.
color_channel = serializers.ChoiceField(
    choices=['red', 'green', 'blue'],
    style={'base_template': 'radio.html'}
)
```

Более подробную информацию можно найти в документации [HTML & Forms](https://ilyachch.gitbook.io/django-rest-framework-russian-documentation/stati/topics/html-and-forms).

***

## Булевы поля

### BooleanField

Булево представление.

При использовании HTML-кодированных форм ввода имейте в виду, что отсутствие значения всегда будет рассматриваться как установка поля в `False`, даже если для него указана опция `default=True`. Это происходит потому, что чекбоксы HTML представляют состояние без флажка в виде отсутствия значение, поэтому DRF воспринимает отсутствие значения как `False`.

Обратите внимание, что в Django 2.1 из `models.BooleanField` был удален именованный аргумент `blank`. До Django 2.1 поля `models.BooleanField` всегда имели значение `blank=True`. Таким образом, начиная с Django 2.1 экземпляры `serializers.BooleanField` по умолчанию будут генерироваться без kwarg `required` (т.е. эквивалентно `required=True`), тогда как в предыдущих версиях Django экземпляры `BooleanField` по умолчанию будут генерироваться с опцией `required=False`. Если вы хотите управлять этим поведением вручную, явно объявите `BooleanField` в классе сериализатора или используйте опцию `extra_kwargs` для установки флага `required`.

Соответствует `django.db.models.fields.BooleanField`.

**Сигнатура:** `BooleanField()`.

***

## Строковые поля

### CharField

Текстовое представление. Опционально проверяет, чтобы текст был короче `max_length` и длиннее `min_length`.

Соответствует `django.db.models.fields.CharField` или `django.db.models.fields.TextField`.

**Сигнатура:** `CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)`.

* `max_length` - Проверяет, что вводимые данные содержат не более этого количества символов.
* `min_length` - Проверяет, что вводимые данные содержат не менее этого количества символов.
* `allow_blank` - Если установлено значение `True`, то пустая строка будет считаться допустимым значением. Если установлено значение `False`, то пустая строка будет считаться недопустимой и вызовет ошибку валидации. По умолчанию `False`.
* `trim_whitespace` - Если установлено значение `True`, то пробельные символы в начале и в конце будут обрезаны. По умолчанию `True`.

Опция `allow_null` также доступна для строковых полей, хотя ее использование не рекомендуется в пользу `allow_blank`. Можно установить и `allow_blank=True`, и `allow_null=True`, но это означает, что для строковых представлений будут допустимы два разных типа пустых значений, что может привести к несоответствию данных и тонким ошибкам в работе приложения.

### EmailField

Текстовое представление, проверяющее, является ли этот текст действительным адресом электронной почты.

Соответствует `django.db.models.fields.EmailField`.

**Сигнатура:** `EmailField(max_length=None, min_length=None, allow_blank=False)`.

### RegexField

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

Соответствует `django.forms.fields.RegexField`.

**Сигнатура:** `RegexField(regex, max_length=None, min_length=None, allow_blank=False)`.

Обязательный аргумент `regex` может быть либо строкой, либо скомпилированным объектом регулярного выражения python.

Для проверки используется `django.core.validators.RegexValidator` от Django.

### SlugField

Поле `RegexField`, которое проверяет вводимые данные на соответствие шаблону `[a-zA-Z0-9_-]+`.

Соответствует `django.db.models.fields.SlugField`.

**Сигнатура:** `SlugField(max_length=50, min_length=None, allow_blank=False)`.

### URLField

Поле `RegexField`, которое проверяет вводимые данные на соответствие шаблону URL. Ожидаются полностью определенные URL вида `http://<host>/<path>`.

Соответствует `django.db.models.fields.URLField`. Для проверки используется `django.core.validators.URLValidator`.

**Сигнатура:** `URLField(max_length=200, min_length=None, allow_blank=False)`.

### UUIDField

Поле, которое гарантирует, что вводимые данные являются правильной строкой UUID. Метод `to_internal_value` возвращает экземпляр `uuid.UUID`. На выходе поле вернет строку в каноническом дефисном формате, например:

```
"de305d54-75b4-431b-adb2-eb6b9e546013"
```

**Сигнатура:** `UUIDField(format='hex_verbose')`.

* `format`: Определяет формат представления значения uuid
  * `'hex_verbose'` - Каноническое шестнадцатеричное представление, включая дефисы: `"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`.
  * `'hex'` - Компактное шестнадцатеричное представление UUID, не включая дефисы: `"5ce0e9a55ffa654bcee01238041fb31a"`.
  * `'int'` - 128-битное целочисленное представление UUID: `"123456789012312313134124512351145145114"`.
  * `'urn'` - RFC 4122 URN-представление UUID: `'urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a'`. Изменение параметров `формата` влияет только на значения представления. Все форматы принимаются функцией `to_internal_value`.

### FilePathField

Поле, выбор которого ограничен именами файлов в определенном каталоге файловой системы

Соответствует `django.forms.fields.FilePathField`.

**Сигнатура:** `FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)`.

* `path` - Абсолютный путь файловой системы к директории, из которой это поле FilePathField должно получить свой выбор.
* `match` - Регулярное выражение в виде строки, которое FilePathField будет использовать для фильтрации имен файлов.
* `recursive` - Указывает, должны ли включаться все подкаталоги пути. По умолчанию `False`.
* `allow_files` - Указывает, должны ли включаться файлы в указанном месте. По умолчанию `True`. Либо это, либо `allow_folders` должно быть `True`.
* `allow_folders` - Указывает, должны ли включаться папки в указанном месте. По умолчанию `False`. Либо это, либо `allow_files` должно быть `True`.

### IPAddressField

Поле, гарантирующее, что вводимые данные являются действительной строкой IPv4 или IPv6.

Соответствует `django.forms.fields.IPAddressField` и `django.forms.fields.GenericIPAddressField`.

**Сигнатура**: `IPAddressField(protocol='both', unpack_ipv4=False, **options)`.

* `protocol` Ограничивает допустимые входы указанным протоколом. Принимаемые значения: `'both'` (по умолчанию), `'IPv4'` или `'IPv6'`. Соответствие не зависит от регистра.
* `unpack_ipv4` Распаковывает сопоставленные IPv4-адреса, например `::ffff:192.0.2.1`. Если эта опция включена, то адрес будет распакован в `192.0.2.1`. По умолчанию отключена. Может использоваться только в том случае, если для протокола установлено значение `'both'`.

***

## Числовые поля

### IntegerField

Целочисленное представление.

Соответствует `django.db.models.fields.IntegerField`, `django.db.models.fields.SmallIntegerField`, `django.db.models.fields.PositiveIntegerField` и `django.db.models.fields.PositiveSmallIntegerField`.

**Сигнатура**: `IntegerField(max_value=None, min_value=None)`.

* `max_value` Проверяет, что предоставленное число не больше этого значения.
* `min_value` Проверяет, что предоставленное число не меньше этого значения.

### FloatField

Представление с плавающей точкой.

Соответствует `django.db.models.fields.FloatField`.

**Сигнатура**: `FloatField(max_value=None, min_value=None)`.

* `max_value` Проверяет, что предоставленное число не больше этого значения.
* `min_value` Проверяет, что предоставленное число не меньше этого значения.

### DecimalField

Десятичное представление, представленное в Python экземпляром `Decimal`.

Соответствует `django.db.models.fields.DecimalField`.

**Сигнатура**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)`.

* `max_digits` Максимальное количество цифр, допустимое в числе. Оно должно быть либо `None`, либо целым числом, большим или равным `decimal_places`.
* `decimal_places` Количество десятичных знаков, которые следует хранить в числе.
* `coerce_to_string` Установите значение `True`, если для представления должны быть возвращены строковые значения, или `False`, если должны быть возвращены объекты `Decimal`. По умолчанию имеет то же значение, что и ключ настроек `COERCE_DECIMAL_TO_STRING`, который будет `True`, если его не переопределить. Если сериализатор возвращает `Decimal` объекты, то окончательный формат вывода будет определяться рендерером. Обратите внимание, что установка `localize` заставит значение быть `True`.
* `max_value` Проверяет, что предоставленное число не больше этого значения.
* `min_value` Проверяет, что предоставленное число не меньше этого значения.
* `localize` Установите значение `True`, чтобы включить локализацию ввода и вывода на основе текущей локали. Это также заставит `coerce_to_string` принять значение `True`. По умолчанию установлено значение `False`. Обратите внимание, что форматирование данных будет включено, если вы установили `USE_L10N=True` в вашем файле настроек.
* `rounding` Устанавливает режим округления, используемый при квантовании с заданной точностью. Допустимые значения: [`decimal` module rounding modes](https://docs.python.org/3/library/decimal.html#rounding-modes). По умолчанию `None`.
* `normalize_output` Нормализует десятичное значение при сериализации. При этом удаляются все нули в конце строки и точность значения изменяется до минимально необходимой, чтобы можно было представить значение без потери данных. По умолчанию имеет значение `False`.

**Пример использования**

Для проверки чисел до 999 с разрешением 2 знака после запятой можно использовать:

```python
serializers.DecimalField(max_digits=5, decimal_places=2)
```

А также для проверки чисел вплоть до миллиарда с разрешением 10 знаков после запятой:

```python
serializers.DecimalField(max_digits=19, decimal_places=10)
```

***

## Поля даты и времени

### DateTimeField

Представление даты и времени.

Соответствует `django.db.models.fields.DateTimeField`.

**Сигнатура:** `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None, default_timezone=None)`.

* `format` - Строка, представляющая формат вывода. Если он не указан, то по умолчанию принимает значение, равное ключу настроек `DATETIME_FORMAT`, который будет `'iso-8601'`, если он не установлен. Установка в строку формата указывает на то, что возвращаемые значения `to_representation` должны быть принудительно приведены к строковому виду. Строки формата описаны ниже. Установка этого значения в `None` указывает, что `to_representation` должен возвращать объекты Python `datetime`. В этом случае кодировка времени будет определяться рендерером.
* `input_formats` - Список строк, представляющих входные форматы, которые могут быть использованы для разбора даты. Если он не указан, будет использоваться настройка `DATETIME_INPUT_FORMATS`, которая по умолчанию принимает значение `['iso-8601']`.
* `default_timezone` - Подкласс `tzinfo` (`zoneinfo` или `pytz`), представляющий часовой пояс. Если он не указан и включен параметр `USE_TZ`, то по умолчанию используется [текущий часовой пояс](https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone). Если `USE_TZ` отключена, то объекты datetime будут наивными.

**Строки формата `DateTimeField`.**

Строки формата могут быть либо [Python strftime formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior), которые явно указывают формат, либо специальной строкой `'iso-8601'`, которая указывает на то, что следует использовать значения в стиле [ISO 8601](https://www.w3.org/TR/NOTE-datetime). (Например, `'2013-01-29T12:34:56.000000Z'`)

Если для формата используется значение `None`, то объекты `datetime` будут возвращаться методом `to_representation`, а окончательное представление на выходе будет определяться классом renderer.

**Поля модели `auto_now` и `auto_now_add`.**

При использовании `ModelSerializer` или `HyperlinkedModelSerializer` обратите внимание, что любые поля модели с `auto_now=True` или `auto_now_add=True` будут использовать поля сериализатора, которые по умолчанию имеют значение `read_only=True`.

Если вы хотите переопределить это поведение, вам нужно будет явно объявить `DateTimeField` в сериализаторе. Например:

```python
class CommentSerializer(serializers.ModelSerializer):
    created = serializers.DateTimeField()

    class Meta:
        model = Comment
```

### DateField

Представление даты.

Соответствует `django.db.models.fields.DateField`.

**Сигнатура:** `DateField(format=api_settings.DATE_FORMAT, input_formats=None)`.

* `format` - Строка, представляющая формат вывода. Если он не указан, то по умолчанию принимает значение, равное ключу настроек `DATE_FORMAT`, который будет `'iso-8601'`, если он не установлен. Установка в строку формата указывает на то, что возвращаемые значения `to_representation` должны быть преобразованы в строковый вывод. Строки формата описаны ниже. Установка этого значения в `None` указывает, что `to_representation` должен возвращать объекты Python `date`. В этом случае кодировка даты будет определяться рендерером.
* `input_formats` - Список строк, представляющих входные форматы, которые могут быть использованы для разбора даты. Если он не указан, будет использоваться настройка `DATE_INPUT_FORMATS`, которая по умолчанию принимает значение `['iso-8601']`.

**Строки формата `DateField`.**

Строки формата могут быть либо [Python strftime formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior), которые явно указывают формат, либо специальной строкой `'iso-8601'`, которая указывает, что должны использоваться даты в стиле [ISO 8601](https://www.w3.org/TR/NOTE-datetime). (например, `'2013-01-29'`)

### TimeField

Представление времени.

Соответствует `django.db.models.fields.TimeField`.

**Сигнатура:** `TimeField(format=api_settings.TIME_FORMAT, input_formats=None)`.

* `format` - строка, представляющая формат вывода. Если он не указан, то по умолчанию принимает значение, равное ключу настроек `TIME_FORMAT`, который будет `'iso-8601'`, если он не установлен. Установка в строку формата указывает на то, что возвращаемые значения `to_representation` должны быть принудительно выведены в строку. Строки формата описаны ниже. Установка этого значения в `None` указывает, что `to_representation` должен возвращать объекты Python `time`. В этом случае кодировка времени будет определяться рендерером.
* `input_formats` - Список строк, представляющих входные форматы, которые могут быть использованы для разбора даты. Если он не указан, будет использоваться настройка `TIME_INPUT_FORMATS`, которая по умолчанию принимает значение `['iso-8601']`.

**Строки формата `TimeField`.**

Строки формата могут быть либо [Python strftime formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior), которые явно указывают формат, либо специальной строкой `'iso-8601'`, которая указывает, что должно использоваться время в стиле [ISO 8601](https://www.w3.org/TR/NOTE-datetime). (например, `'12:34:56.000000'`)

### DurationField

Представление длительности. Соответствует `django.db.models.fields.DurationField`.

В `validated_data` для этих полей будет содержаться экземпляр `datetime.timedelta`. Он представляет собой строку, следующую формату `'[DD] [HH:[MM:]]ss[.uuuuuu]'`.

**Сигнатура:** `DurationField(max_value=None, min_value=None)`.

* `max_value` Проверяет, что предоставленная продолжительность не больше этого значения.
* `min_value` Проверяет, что предоставленная продолжительность не меньше этого значения.

***

## Поля выбора

### ChoiceField

Поле, которое может принимать значение из ограниченного набора вариантов.

Используется `ModelSerializer` для автоматической генерации полей, если соответствующее поле модели содержит аргумент `choices=...`.

**Сигнатура:** `ChoiceField(choices)`.

* `choices` - Список допустимых значений, или список кортежей `(key, display_name)`.
* `allow_blank` - Если установлено значение `True`, то пустая строка будет считаться допустимым значением. Если установлено значение `False`, то пустая строка будет считаться недопустимой и вызовет ошибку валидации. По умолчанию `False`.
* `html_cutoff` - Если установлено, то это будет максимальное количество вариантов, которые будут отображаться в выпадающем списке HTML select. Может использоваться для того, чтобы автоматически генерируемые поля выбора с очень большим количеством возможных вариантов выбора не мешали отрисовке шаблона. По умолчанию `None`.
* `html_cutoff_text` - Если установлено, то будет отображаться текстовый индикатор, если максимальное количество элементов было отсечено в выпадающем списке HTML select. По умолчанию `"More than {count} items..."`.

Оба параметра `allow_blank` и `allow_null` являются допустимыми для `ChoiceField`, хотя настоятельно рекомендуется использовать только один из них, а не оба. `allow_blank` следует предпочесть для текстовых вариантов, а `allow_null` - для числовых или других нетекстовых вариантов.

### MultipleChoiceField

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

**Сигнатура:** `MultipleChoiceField(choices)`.

* `choices` - Список допустимых значений, или список кортежей `(key, display_name)`.
* `allow_blank` - Если установлено значение `True`, то пустая строка будет считаться допустимым значением. Если установлено значение `False`, то пустая строка будет считаться недопустимой и вызовет ошибку валидации. По умолчанию `False`.
* `html_cutoff` - Если установлено, то это будет максимальное количество вариантов, которые будут отображаться в выпадающем списке HTML select. Может использоваться для того, чтобы автоматически генерируемые поля выбора с очень большим количеством возможных вариантов выбора не мешали отрисовке шаблона. По умолчанию `None`.
* `html_cutoff_text` - Если установлено, то будет отображаться текстовый индикатор, если максимальное количество элементов было отсечено в выпадающем списке HTML select. По умолчанию `"More than {count} items..."`.

Как и в случае с `ChoiceField`, оба параметра `allow_blank` и `allow_null` являются допустимыми, хотя настоятельно рекомендуется использовать только один из них, а не оба. `allow_blank` следует предпочесть для текстовых вариантов, а `allow_null` - для числовых или других нетекстовых вариантов.

***

## Поля для загрузки файлов

**Парсеры и загрузка файлов.**

Классы `FileField` и `ImageField` подходят только для использования с `MultiPartParser` или `FileUploadParser`. Большинство парсеров, например, JSON, не поддерживают загрузку файлов. Для работы с загруженными файлами в Django используются штатные [FILE\_UPLOAD\_HANDLERS](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS).

### FileField

Представление файла. Выполняет стандартную для Django проверку `FileField`.

Соответствует `django.forms.fields.FileField`.

**Сигнатура:** `FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`.

* `max_length` - Указывает максимальную длину имени файла.
* `allow_empty_file` - Указывает, разрешены ли пустые файлы.
* `use_url` - Если установлено значение `True`, то для выходного представления будут использоваться строковые значения URL. Если установлено значение `False`, то для вывода будут использоваться строковые значения имен файлов. По умолчанию принимает значение ключа настроек `UPLOADED_FILES_USE_URL`, которое равно `True`, если не установлено иное.

### ImageField

Представление изображения. Проверяет соответствие содержимого загруженного файла известному формату изображения.

Соответствует `django.forms.fields.ImageField`.

**Сигнатура:** `ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`.

* `max_length` - Указывает максимальную длину имени файла.
* `allow_empty_file` - Указывает, разрешены ли пустые файлы.
* `use_url` - Если установлено значение `True`, то для выходного представления будут использоваться строковые значения URL. Если установлено значение `False`, то для вывода будут использоваться строковые значения имен файлов. По умолчанию принимает значение ключа настроек `UPLOADED_FILES_USE_URL`, которое равно `True`, если не установлено иное.

Требуется либо пакет `Pillow`, либо пакет `PIL`. Рекомендуется использовать пакет `Pillow`, так как пакет `PIL` больше активно не поддерживается.

***

## Составные поля

### ListField

Класс поля, который проверяет список объектов.

**Сигнатура**: `ListField(child=<A_FIELD_INSTANCE>, allow_empty=True, min_length=None, max_length=None)`.

* `child` - Экземпляр поля, который должен использоваться для проверки объектов в списке. Если этот аргумент не указан, то объекты в списке не будут проверяться.
* `allow_empty` - Указывает, разрешены ли пустые списки.
* `min_length` - Проверяет, что список содержит не менее этого количества элементов.
* `max_length` - Проверяет, что список содержит не более этого количества элементов.

Например, для проверки списка целых чисел вы можете использовать что-то вроде следующего:

```python
scores = serializers.ListField(
   child=serializers.IntegerField(min_value=0, max_value=100)
)
```

Класс `ListField` также поддерживает декларативный стиль, который позволяет писать многократно используемые классы полей списков.

```python
class StringListField(serializers.ListField):
    child = serializers.CharField()
```

Теперь мы можем повторно использовать наш пользовательский класс `StringListField` во всем нашем приложении, без необходимости указывать для него аргумент `child`.

### DictField

Класс поля, который проверяет словарь объектов. Ключи в `DictField` всегда предполагаются как строковые значения.

**Сигнатура**: `DictField(child=<A_FIELD_INSTANCE>, allow_empty=True)`.

* `child` - Экземпляр поля, который должен использоваться для проверки значений в словаре. Если этот аргумент не указан, то значения в отображении не будут проверяться.
* `allow_empty` - Указывает, разрешены ли пустые словари.

Например, чтобы создать поле, которое проверяет сопоставление строк со строками, вы должны написать что-то вроде этого:

```python
document = DictField(child=CharField())
```

Вы также можете использовать декларативный стиль, как в случае с `ListField`. Например:

```python
class DocumentField(DictField):
    child = CharField()
```

### HStoreField

Предварительно настроенное `DictField`, совместимое с `HStoreField` от Django для postgres.

**Сигнатура**: `HStoreField(child=<A_FIELD_INSTANCE>, allow_empty=True)`.

* `child` - экземпляр поля, который используется для проверки значений в словаре. По умолчанию дочернее поле принимает как пустые строки, так и нулевые значения.
* `allow_empty` - Указывает, разрешены ли пустые словари.

Обратите внимание, что дочернее поле **должно** быть экземпляром `CharField`, так как расширение hstore хранит значения в виде строк.

### JSONField

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

**Сигнатура**: `JSONField(binary, encoder)`.

* `binary` - Если установлено значение `True`, то поле будет выводить и проверять строку, закодированную в JSON, а не примитивную структуру данных. По умолчанию `False`.
* `encoder` - Используйте этот JSON-кодер для сериализации входного объекта. По умолчанию `None`.

***

## Разные поля

### ReadOnlyField

Класс поля, который просто возвращает значение поля без изменений.

Это поле используется по умолчанию в `ModelSerializer` при включении имен полей, относящихся к атрибуту, а не к полю модели.

**Сигнатура**: `ReadOnlyField()`.

Например, если бы `has_expired` было свойством модели `Account`, то следующий сериализатор автоматически сгенерировал бы его как `ReadOnlyField`:

```python
class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'has_expired']
```

### HiddenField

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

**Сигнатура**: `HiddenField()`.

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

```python
modified = serializers.HiddenField(default=timezone.now)
```

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

Другие примеры по `HiddenField` смотрите в документации [validators](https://ilyachch.gitbook.io/django-rest-framework-russian-documentation/overview/navigaciya-po-api/validators).

***

**Примечание:** `HiddenField()` не появляется в сериализаторе `partial=True` (при выполнении запроса `PATCH`). Это поведение может измениться в будущем, следите за обновлениями на [github discussion](https://github.com/encode/django-rest-framework/discussions/8259).

***

### ModelField

Общее поле, которое может быть привязано к любому произвольному полю модели. Класс `ModelField` делегирует задачу сериализации/десериализации связанному с ним полю модели. Это поле можно использовать для создания полей сериализатора для пользовательских полей модели, без необходимости создавать новое пользовательское поле сериализатора.

Это поле используется `ModelSerializer` для соответствия классам полей пользовательской модели.

**Сигнатура:** `ModelField(model_field=<Django ModelField instance>)`.

Класс `ModelField` обычно предназначен для внутреннего использования, но при необходимости может быть использован в вашем API. Чтобы правильно инстанцировать `ModelField`, ему должно быть передано поле, привязанное к инстанцированной модели. Например: `ModelField(model_field=MyModel()._meta.get_field('custom_field'))`.

### SerializerMethodField

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

**Сигнатура**: `SerializerMethodField(method_name=None)`.

* `method_name` - Имя метода в сериализаторе, который будет вызван. Если оно не включено, то по умолчанию используется `get_<имя_поля>`.

Метод сериализатора, на который ссылается аргумент `имя_метода`, должен принимать единственный аргумент (в дополнение к `self`), которым является сериализуемый объект. Он должен возвращать все, что вы хотите включить в сериализованное представление объекта. Например:

```python
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = '__all__'

    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days
```

***

## Пользовательские поля

Если вы хотите создать пользовательское поле, вам нужно создать подкласс `Field`, а затем переопределить один или оба метода `.to_representation()` и `.to_internal_value()`. Эти два метода используются для преобразования между исходным типом данных и примитивным, сериализуемым типом данных. Примитивными типами данных обычно являются число, строка, булево значение, `date`/`time`/`datetime` или `None`. Также это может быть любой список или словарь, содержащий только другие примитивные объекты. Могут поддерживаться и другие типы, в зависимости от используемого рендерера.

Метод `.to_representation()` вызывается для преобразования исходного типа данных в примитивный, сериализуемый тип данных.

Метод `.to_internal_value()` вызывается для восстановления примитивного типа данных в его внутреннее python-представление. Этот метод должен вызвать ошибку `serializers.ValidationError`, если данные недействительны.

### Примеры

#### Базовое пользовательское поле

Давайте рассмотрим пример сериализации класса, представляющего значение цвета RGB:

```python
class Color:
    """
    A color represented in the RGB colorspace.
    """
    def __init__(self, red, green, blue):
        assert(red >= 0 and green >= 0 and blue >= 0)
        assert(red < 256 and green < 256 and blue < 256)
        self.red, self.green, self.blue = red, green, blue

class ColorField(serializers.Field):
    """
    Color objects are serialized into 'rgb(#, #, #)' notation.
    """
    def to_representation(self, value):
        return "rgb(%d, %d, %d)" % (value.red, value.green, value.blue)

    def to_internal_value(self, data):
        data = data.strip('rgb(').rstrip(')')
        red, green, blue = [int(col) for col in data.split(',')]
        return Color(red, green, blue)
```

По умолчанию значения полей рассматриваются как сопоставление с атрибутом объекта. Если вам нужно настроить доступ к значению поля и его установку, вам нужно переопределить `.get_attribute()` и/или `.get_value()`.

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

```python
class ClassNameField(serializers.Field):
    def get_attribute(self, instance):
        # We pass the object instance onto `to_representation`,
        # not just the field attribute.
        return instance

    def to_representation(self, value):
        """
        Serialize the value's class name.
        """
        return value.__class__.__name__
```

#### Вызов ошибок проверки

Наш класс `ColorField`, описанный выше, в настоящее время не выполняет никакой проверки данных. Чтобы указать на недопустимые данные, мы должны вызвать ошибку `serializers.ValidationError`, как показано ниже:

```python
def to_internal_value(self, data):
    if not isinstance(data, str):
        msg = 'Incorrect type. Expected a string, but got %s'
        raise ValidationError(msg % type(data).__name__)

    if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
        raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.')

    data = data.strip('rgb(').rstrip(')')
    red, green, blue = [int(col) for col in data.split(',')]

    if any([col > 255 or col < 0 for col in (red, green, blue)]):
        raise ValidationError('Value out of range. Must be between 0 and 255.')

    return Color(red, green, blue)
```

Метод `.fail()` - это ярлык для вызова `ValidationError`, который принимает строку сообщения из словаря `error_messages`. Например:

```python
default_error_messages = {
    'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
    'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
    'out_of_range': 'Value out of range. Must be between 0 and 255.'
}

def to_internal_value(self, data):
    if not isinstance(data, str):
        self.fail('incorrect_type', input_type=type(data).__name__)

    if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
        self.fail('incorrect_format')

    data = data.strip('rgb(').rstrip(')')
    red, green, blue = [int(col) for col in data.split(',')]

    if any([col > 255 or col < 0 for col in (red, green, blue)]):
        self.fail('out_of_range')

    return Color(red, green, blue)
```

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

#### Использование `source='*'`

Здесь мы рассмотрим пример *плоской* модели `DataPoint` с атрибутами `x_coordinate` и `y_coordinate`.

```python
class DataPoint(models.Model):
    label = models.CharField(max_length=50)
    x_coordinate = models.SmallIntegerField()
    y_coordinate = models.SmallIntegerField()
```

Используя пользовательское поле и `source='*'`, мы можем предоставить вложенное представление пары координат:

```python
class CoordinateField(serializers.Field):

    def to_representation(self, value):
        ret = {
            "x": value.x_coordinate,
            "y": value.y_coordinate
        }
        return ret

    def to_internal_value(self, data):
        ret = {
            "x_coordinate": data["x"],
            "y_coordinate": data["y"],
        }
        return ret

class DataPointSerializer(serializers.ModelSerializer):
    coordinates = CoordinateField(source='*')

    class Meta:
        model = DataPoint
        fields = ['label', 'coordinates']
```

Обратите внимание, что в этом примере не предусмотрена валидация. Отчасти по этой причине в реальном проекте вложенность координат может быть лучше обработана с помощью вложенного сериализатора используя `source='*'`, с двумя экземплярами `IntegerField`, каждый из которых имеет свой собственный `source` указывающий на соответствующее поле.

Ключевыми моментами из этого примера являются следующие:

* `to_representation` передается весь объект `DataPoint`, который должен быть отображен в нужный вывод.

  ```python
  >>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2)
  >>> out_serializer = DataPointSerializer(instance)
  >>> out_serializer.data
  ReturnDict([('label', 'Example'), ('coordinates', {'x': 1, 'y': 2})])
  ```
* Если только наше поле не будет доступно только для чтения, `to_internal_value` должно возвращать дикту, подходящую для обновления целевого объекта. При использовании `source='*'`, возврат из `to_internal_value` будет обновлять корневой словарь данных, а не один ключ.

  ```python
  >>> data = {
  ...     "label": "Second Example",
  ...     "coordinates": {
  ...         "x": 3,
  ...         "y": 4,
  ...     }
  ... }
  >>> in_serializer = DataPointSerializer(data=data)
  >>> in_serializer.is_valid()
  True
  >>> in_serializer.validated_data
  OrderedDict([('label', 'Second Example'),
              ('y_coordinate', 4),
              ('x_coordinate', 3)])
  ```

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

```python
class NestedCoordinateSerializer(serializers.Serializer):
    x = serializers.IntegerField(source='x_coordinate')
    y = serializers.IntegerField(source='y_coordinate')

class DataPointSerializer(serializers.ModelSerializer):
    coordinates = NestedCoordinateSerializer(source='*')

    class Meta:
        model = DataPoint
        fields = ['label', 'coordinates']
```

Здесь отображение между парами атрибутов цели и источника (`x` и `x_coordinate`, `y` и `y_coordinate`) обрабатывается в объявлениях `IntegerField`. Это наш `NestedCoordinateSerializer`, который принимает `source='*'`.

Наш новый `DataPointSerializer` демонстрирует то же поведение, что и подход с пользовательскими полями.

Сериализация:

```python
>>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data
ReturnDict([('label', 'testing'),
            ('coordinates', OrderedDict([('x', 1), ('y', 2)]))])
```

Десериализация:

```python
>>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid()
True
>>> in_serializer.validated_data
OrderedDict([('label', 'still testing'),
             ('x_coordinate', 3),
             ('y_coordinate', 4)])
```

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

```python
>>> invalid_data = {
...     "label": "still testing",
...     "coordinates": {
...         "x": 'a',
...         "y": 'b',
...     }
... }
>>> invalid_serializer = DataPointSerializer(data=invalid_data)
>>> invalid_serializer.is_valid()
False
>>> invalid_serializer.errors
ReturnDict([('coordinates',
             {'x': ['A valid integer is required.'],
              'y': ['A valid integer is required.']})])
```

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

## Пакеты сторонних производителей

Также доступны следующие пакеты сторонних производителей.

### Составные поля DRF

Пакет [drf-compound-fields](https://drf-compound-fields.readthedocs.io) предоставляет "составные" поля сериализатора, такие как списки простых значений, которые могут быть описаны другими полями, а не сериализаторами с опцией `many=True`. Также предоставляются поля для типизированных словарей и значений, которые могут быть либо определенным типом, либо списком элементов этого типа.

### Дополнительные поля DRF

Пакет [drf-extra-fields](https://github.com/Hipo/drf-extra-fields) предоставляет дополнительные поля сериализатора для DRF, включая классы `Base64ImageField` и `PointField`.

### djangorestframework-recursive

Пакет [djangorestframework-recursive](https://github.com/heywbj/django-rest-framework-recursive) предоставляет `RecursiveField` для сериализации и десериализации рекурсивных структур.

### django-rest-framework-gis

Пакет [django-rest-framework-gis](https://github.com/djangonauts/django-rest-framework-gis) предоставляет географические дополнения для DRF, такие как поле `GeometryField` и сериализатор GeoJSON.

### django-rest-framework-hstore

Пакет [django-rest-framework-hstore](https://github.com/djangonauts/django-rest-framework-hstore) предоставляет `HStoreField` для поддержки поля модели [django-hstore](https://github.com/djangonauts/django-hstore) `DictionaryField`.
