Когда вы разрабатываете API, всегда есть ситуации, когда вам не нужны все поля из модели. Иногда вы хотите скрыть чувствительные данные, сделать поле только для чтения или добавить дополнительную валидацию. DRF предоставляет мощные инструменты для управления этими нюансами.
Например, вам может понадобиться:
- Ограничить доступ к конфиденциальным полям (например, скрыть пароль пользователя).
- Сделать поле доступным только для чтения, чтобы его нельзя было изменить через API.
- Настроить поле для возврата данных в удобном формате (например, форматировать дату).
Пора начать. Ведь как говорится, «хороший код — это читаемый код, а хороший API — это настраиваемый API».
Настройка полей в сериализаторе
Основной способ управлять списком полей (удалять или добавнять) в сериализаторе — это использовать атрибут fields в классе Meta.
from rest_framework import serializers
from myapp.models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'price'] # Указываем только нужные поля
Если вам нужно исключить одно или несколько полей, используйте атрибут exclude:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
exclude = ['discount'] # Исключаем поле "discount"
атрибуты fields и exclude являются взаимоисключающими. Не пытайтесь указать их оба одновременно, иначе DRF «обидится» и бросит ошибку.
Поля только для чтения и записи
Вы можете управлять доступом к полям с помощью параметров read_only_fields или write_only_fields.
Пример: поле только для чтения. Поле доступно клиенту только при отправке данных, но изменять его через API нельзя.
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'created_at']
read_only_fields = ['created_at'] # Поле "created_at" только для чтения
Пример: поле только для записи. Поле можно отправить на сервер, но оно не будет возвращаться клиенту.
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'password']
extra_kwargs = {'password': {'write_only': True}} # "password" - только для записи
extra_kwargs — универсальный способ добавить кастомное поведение для отдельных полей.
Кастомизация полей
Если вам требуется изменить поведение поля (например, его тип или параметры), можно определить поле явно. Это может быть полезно, если вы хотите настроить его атрибуты.
Приведём пример. Допустим, нужно ограничить минимальное и максимальное значение для цены товара:
class ProductSerializer(serializers.ModelSerializer):
price = serializers.DecimalField(max_digits=10, decimal_places=2, min_value=0)
class Meta:
model = Product
fields = ['id', 'name', 'price']
Когда клиент отправит отрицательное значение, он получит ошибку валидации. И это прекрасно, ведь мы защитили нашу базу данных от «минусовых ценников».
Валидация полей
DRF поддерживает встроенные валидаторы и позволяет легко добавлять кастомные проверки для полей.
Используйте встроенные валидаторы для стандартных проверок: длина строки, диапазон чисел и т.д.
class ProductSerializer(serializers.ModelSerializer):
name = serializers.CharField(max_length=100, min_length=3)
price = serializers.DecimalField(max_digits=10, decimal_places=2, min_value=1)
class Meta:
model = Product
fields = ['id', 'name', 'price']
Для кастомных проверок можно определить метод validate_<field_name>:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'price']
def validate_price(self, value):
if value > 10000:
raise serializers.ValidationError("Цена не может быть больше 10,000.")
return value
Метод возвращает значение, если оно прошло валидацию.
Скрытие полей
Иногда вы вообще не хотите показывать определенное поле клиенту. Например, поле internal_code нужно только для внутреннего использования.
Пример. Вы можете просто не включать это поле в список fields. Однако, если нужно более гибкое решение, внезапно приходят на помощь SerializerMethodField.
class ProductSerializer(serializers.ModelSerializer):
internal_code = serializers.SerializerMethodField()
class Meta:
model = Product
fields = ['id', 'name', 'price']
def get_internal_code(self, obj):
return None # Мы вернем "None", чтобы клиенту показалось, что это поле не существует
Работа с дополнительной информацией
Иногда требуется включить в сериализатор вычисляемое поле. Например, добавим к товару поле total_price, которое рассчитывается исходя из цены и количества:
class ProductSerializer(serializers.ModelSerializer):
total_price = serializers.SerializerMethodField()
class Meta:
model = Product
fields = ['id', 'name', 'price', 'quantity', 'total_price']
def get_total_price(self, obj):
return obj.price * obj.quantity
Используйте SerializerMethodField для вычисляемых значений или данных, которые не хранятся в базе.
Поля с пользовательскими форматами
Что, если клиенту нужно вернуть дату в специфическом формате? Например, вместо стандартного ISO формата, нам нужен DD/MM/YYYY.
class ProductSerializer(serializers.ModelSerializer):
created_at = serializers.DateTimeField(format="%d/%m/%Y")
class Meta:
model = Product
fields = ['id', 'name', 'price', 'created_at']
Теперь клиент получит дату в удобном для него виде.
Практическое задание
Теперь, когда вы освоили настройку полей в сериализаторах, попробуйте следующие задания:
- Создайте сериализатор для модели пользователя, включая только поля
id,username, иemail. Полеemailдолжно быть доступно только для чтения. - Расширьте модель товара, добавив поле
discount_price, которое вычисляется какprice * (1 - discount/100)с использованиемSerializerMethodField. - Постройте валидацию, чтобы поле
discountне превышало 50%.
Эти задания помогут закрепить материал. А если что-то не получается, просто представьте, как ваш будущий API радует клиентов. Ну кто не старается ради такой мотивации? 😄
Теперь вы знаете, как управлять полями сериализаторов в Django REST Framework. Впереди нас ждут более сложные задачи — вложенные сериализаторы и работа со связанными объектами!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ