Коли ти розробляєш 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. Попереду нас чекають більш складні завдання — вкладені серіалізатори та робота з пов’язаними об’єктами!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ