Модуль 27

Serializers та API views

Це чудовий вибір теми. Serializers та API Views — це "хліб і масло" сучасної веб-розробки, особливо якщо ми говоримо про Django REST Framework (DRF) або схожі патерни в інших мовах.

Вмикаймо "режим CS50". Поїхали!


🎓 CS50: Serializers та API Views. Як навчити Python говорити мовою Інтернету

Привіт, друзі! Це CS50 (Ukrainian Edition).

Сьогодні ми розберемо тему, яка перетворює ваш "глухонімий" код на комунікабельного генія, здатного спілкуватися з усім світом — від iPhone-додатків до JavaScript-фронтенду.


1. 🔥 Вступ: Проблема Вавилонської вежі

Уявіть ситуацію. Ви створили геніальну базу даних на Python. У вас є об'єкт User (Користувач), у якого є ім'я, дата реєстрації, хеш пароля і зв'язок з іншими таблицями. Це складний, багатий об'єкт у пам'яті сервера.

Але тут приходить Фронтенд-розробник (назвемо його Марк) і каже: "Ей, надішли мені дані користувача, я хочу відобразити їх на сторінці!"

Ви кидаєте йому свій Python-об'єкт. Марк дивиться на вас круглими очима. Його JavaScript не розуміє Python-об'єктів. Його React-додаток не знає, що таке "посилання на об'єкт у пам'яті". Йому потрібен текст. Конкретніше — JSON.

Риторичне запитання: Як перетворити складний об'єкт Python (з методами, типами даних datetime, зв'язками) у простий текстовий рядок JSON, який зрозуміє будь-хто? І як зробити зворотний процес, коли Марк надсилає нам дані для реєстрації?

Аналогія: Уявіть, що ваш Python-об'єкт — це зібрана шафа з IKEA. Вона стоїть у кімнаті (пам'яті), вона функціональна. Але щоб надіслати цю шафу другові поштою (через Інтернет), ви не можете запхати її в конверт цілою. Вам потрібно її розібрати (серіалізувати) в пласку коробку з інструкцією (JSON). А ваш друг, отримавши коробку, має зібрати її назад (десеріалізувати), щоб отримати шафу.

Без Serializers та API Views ваш сервер — це острів, на який ніхто не може потрапити.


2. 🧠 Теоретична база (Що під капотом?)

Давайте розберемо два ключові поняття. Не бійтеся термінів, логіка проста.

1. Serializer (Серіалізатор) — Це перекладач

Це компонент, який стоїть між вашою Базою Даних і Інтернетом. * Задача "на вихід" (Serialization): Взяти модель (Python об'єкт), вибрати потрібні поля (ми ж не хочемо віддавати пароль?), перетворити datetime у рядок "2023-10-27" і зробити з цього звичайний словник (dictionary). * Задача "на вхід" (Deserialization): Отримати JSON від користувача, перевірити його (валідaція) і перетворити на Python об'єкт для збереження в БД.

Запам'ятайте: Серіалізатор не зберігає дані сам по собі. Він лише готує їх. Він перевіряє: "Чи правильний формат email? Чи є обов'язкові поля?"

2. API View (В'юшка) — Це менеджер вікна

Серіалізатор — це інструмент. А хто ним користується? API View. Це точка входу (endpoint). Коли ви переходите за посиланням /api/users/, запит потрапляє в API View.

Як це працює крок за кроком: 1. Request: Приходить запит. 2. API View: "О, це запит на отримання даних!" 3. Query: Дістає дані з БД. 4. Serializer: "Серіалізаторе, перетвори ці дані на JSON, будь ласка." 5. Response: Віддає JSON клієнту.


3. 🧪 Приклади (Код у студію!)

Ми будемо використовувати Django REST Framework (DRF), бо це стандарт індустрії.

Етап 1: Модель (Що ми маємо)

У нас є проста модель піци.

# models.py
class Pizza(models.Model):
    name = models.CharField(max_length=100)
    price = models.IntegerField()
    is_spicy = models.BooleanField(default=False)

Етап 2: Найпростіший Serializer

Що ви очікуєте побачити? Просто клас, який каже, які поля ми хочемо "світити" назовні.

# serializers.py
from rest_framework import serializers

class PizzaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pizza
        fields = ['id', 'name', 'price', 'is_spicy']

Пояснення: Ми кажемо: "Візьми модель Pizza і перетвори ці 4 поля". ModelSerializer — це магія, яка сама знає, що name це текст, а price це число.

Етап 3: API View (Зв'язуємо все разом)

Тепер нам треба "вікно видачі".

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Pizza
from .serializers import PizzaSerializer

class PizzaListAPI(APIView):
    # Метод для обробки GET-запиту (отримання даних)
    def get(self, request):
        pizzas = Pizza.objects.all() # 1. Беремо піци з БД
        serializer = PizzaSerializer(pizzas, many=True) # 2. Перетворюємо (many=True бо піц багато)
        return Response(serializer.data) # 3. Віддаємо JSON

Етап 4: Ускладнюємо (POST запит — створення піци)

А як щодо замовлення нової піци? Питання до студента: Де, на вашу думку, має відбуватися перевірка того, що ціна не від’ємна? У View чи в Serializer?

Правильна відповідь: У Serializer.

# views.py (додаємо метод post)
    def post(self, request):
        # 1. Запихаємо дані від клієнта в серіалізатор
        serializer = PizzaSerializer(data=request.data)

        # 2. Перевіряємо, чи дані валідні (чи є назва? чи ціна — число?)
        if serializer.is_valid():
            serializer.save() # 3. Зберігаємо в БД
            return Response(serializer.data, status=201) # Успіх!

        # 4. Якщо помилка — кажемо, що не так
        return Response(serializer.errors, status=400)

4. 🛠 Практична частина

Час забруднити руки кодом! Відкрийте свій IDE.

  1. 🔹 Копіпаст-майстер: Створіть модель Student (ім'я, вік, курс). Напишіть для неї Serializer і APIView, який повертає список студентів (GET).
  2. 🔹 Фейсконтроль: Додайте у свій APIView метод POST. Спробуйте надіслати JSON, де замість віку вказано слово "двадцять". Подивіться, яку помилку поверне DRF. (Це зробить is_valid() автоматично).
  3. 🔹 Кастомна логіка: У вашому серіалізаторі додайте перевірку (Validation method), щоб не можна було додати студента, молодшого за 18 років.
    • Підказка: гугліть def validate_age(self, value):.
  4. 🔹 Приховане поле: Змініть Serializer так, щоб поле id не поверталося клієнту, але поверталося нове поле description, яке вигадується на льоту (наприклад, рядок "Студент {ім'я} навчається на {курс} курсі").
    • Підказка: SerializerMethodField.
  5. 🔹 Кейс "Інстаграм": Уявіть, що ви робите API для постів. Користувач надсилає текст і ID автора.
    • Питання: Що станеться, якщо користувач надішле ID автора, якого не існує? Як Серіалізатор на це відреагує? Перевірте це на практиці.

5. 💡 Мислення як у розробника

Як відрізнити новачка від профі в цій темі?

1. "Товсті" серіалізатори, "худі" в'юшки. Новачки часто пхають купу перевірок (if price < 0) прямо у views.py. Профі знає: API View має лише керувати трафіком (прийняв -> віддав). Вся логіка валідації та збереження має жити в Serializer. Це дозволяє використовувати той самий серіалізатор в різних місцях.

2. Довіряй, але перевіряй. Ніколи, чуєте, НІКОЛИ не довіряйте request.data без виклику serializer.is_valid(). Якщо ви спробуєте зберегти "сирі" дані в БД, ви отримаєте або зламану базу, або діру в безпеці.

3. Серіалізатор — це не тільки для БД. Ви можете використовувати серіалізатори для валідації будь-яких вхідних даних, навіть якщо ви нічого не зберігаєте в базу (наприклад, форма зворотного зв'язку, яка просто шле email).


6. 🧩 Підсумок

Отже, що ми маємо сьогодні в сухому залишку:

  1. Python і Web говорять різними мовами. JSON — це мова-посередник.
  2. Serializer — це перекладач і контролер якості. Він перетворює об'єкти в JSON і перевіряє вхідні дані.
  3. API View — це менеджер, який приймає HTTP-запити (GET, POST) і викликає Серіалізатор.

Тепер ви вмієте: створювати API, яке може "годувати" даними мобільний додаток або React-сайт. Ви офіційно стали Backend-розробником, з яким можна мати справу!

Наступного разу: Ви помітили, що зараз будь-хто може видалити або створити піцу? Це небезпечно. На наступному уроці ми поговоримо про Authentication & Permissions (Аутентифікацію та Дозволи). Ми навчимо наш API запитувати: "А ти хто такий?" перед тим, як дозволити редагувати дані.

А поки що — це був CS50! 💻👋