Модуль 12

Поля моделей та звʼязки між таблицями

Ось готовий урок, створений спеціально за твоїм запитом, у стилі CS50 — енергійно, зрозуміло і з фокусом на те, як це працює насправді.


🎓 Урок: Поля моделей та звʼязки між таблицями

(Або: Чому Excel — це не база даних, і як навести лад у хаосі)


1. 🔥 Вступ: Проблема дублювання (або "Ефект стікера")

Уявіть, що ви керуєте невеликою бібліотекою. Спочатку у вас всього 10 книг. Ви берете звичайний блокнот (або Excel-таблицю) і пишете:

Назва книги Автор Жанр
Кобзар Тарас Шевченко Поезія
Гайдамаки Т.Г. Шевченко Поема
Катерина Шевченко Тарас Класика

Все виглядає непогано, правда? Але подивіться уважніше.

Запитання до вас: Скільки унікальних авторів у цій таблиці? Для комп’ютера — три. 1. "Тарас Шевченко" 2. "Т.Г. Шевченко" 3. "Шевченко Тарас"

Коли ви захочете знайти всі книги Шевченка, комп’ютер скаже: "Якого саме? Цього, того чи ось цього?". Це катастрофа.

А що, як Шевченко вирішить змінити псевдонім? Вам доведеться бігати по всьому блокноту і виправляти це в тисячі рядків. Це неефективно, повільно і небезпечно (можна щось пропустити).

Ось навіщо нам потрібні Моделі та Зв’язки. Ми хочемо написати ім’я автора один раз і просто посилатися на нього. Як у бібліотечному каталозі: картка автора окремо, картка книги окремо.

Сьогодні ми перетворимо хаос на структуру.


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

У світі розробки (особливо веб-розробки, як у Django чи Laravel) ми використовуємо ORM. Не лякайтеся абревіатури. Це просто "перекладач" з мови об'єктів (Python, PHP, JS) на мову бази даних (SQL).

🧱 Поля (Fields) — це ваші контейнери

Коли ми створюємо таблицю, ми повинні суворо сказати базі даних, що саме ми туди кладемо.

  • CharField (Рядок): Для коротких текстів (Ім'я, Назва). Уявіть це як стікер — місця мало, пишемо швидко.
  • TextField (Текст): Для великих статей. Це вже цілий зошит.
  • IntegerField (Число): Тільки цілі числа (Кількість сторінок). Ніяких "3.5 сторінки".
  • DateField (Дата): Календарик.

Інтуїтивно: База даних — це педант. Якщо ви скажете, що поле для дати, вона ніколи не дозволить записати туди слово "вчора". І це рятує нас від помилок!

🔗 Зв’язки (Relationships) — магія посилань

Тут починається найцікавіше. Є три типи стосунків між даними:

  1. Один-до-Багатьох (One-to-Many):
    • Приклад: Один Автор — Багато Книг.
    • Як це працює: У таблиці "Книги" ми не пишемо ім'я автора. Ми пишемо його ID (унікальний номер).
  2. Багато-до-Багатьох (Many-to-Many):
    • Приклад: Піца та Інгредієнти. Одна піца має багато інгредієнтів. Один інгредієнт (сир) використовується в багатьох піцах.
    • Як це працює: Створюється третя, прихована "таблиця-посередник", де записано: "Піца №1 дружить з Інгредієнтом №5".
  3. Один-до-Одного (One-to-One):
    • Приклад: Громадянин і Паспорт. У одного громадянина — один дійсний паспорт.
    • Навіщо: Щоб не пхати все в одну гігантську таблицю.

3. 🧪 Приклади (Код, який говорить)

Уявімо, що ми пишемо код для блогу (класика CS50!). Використаємо псевдокод, схожий на Python/Django.

Приклад 1: Проста модель (Без зв'язків)

Спершу нам потрібен користувач.

class User(Model):
    name = CharField(max_length=100)  # Ім'я, обмежене довжиною
    email = EmailField()              # Перевіряє наявність @
    is_active = BooleanField()        # Так/Ні

Що очікуємо? Таблицю в базі, де є колонки id, name, email, is_active. Все просто.


Приклад 2: Один-до-Багатьох (Реальний проєкт)

Тепер користувач хоче написати пост.

Питання: Як сказати базі, що цей пост належить саме цьому юзеру?

class Post(Model):
    title = CharField(max_length=200)
    content = TextField()

    # МАГІЯ ТУТ 👇
    author = ForeignKey(User, on_delete=CASCADE)

Розбір польотів: 1. ForeignKey — це "Зовнішній Ключ". Це стрілка, яка вказує на модель User. 2. on_delete=CASCADE — це дуже важливо! Це інструкція: "Якщо ми видалимо користувача, що робити з його постами?". * CASCADE: Видалити і пости теж (щоб не було сміття). * SET_NULL: Залишити пости, але в полі автора поставити "Анонім".


Приклад 3: Багато-до-Багатьох (Рівень PRO)

Теги! (Наприклад: #Technology, #Life, #Coding). Один пост може мати багато тегів. Один тег може бути на багатьох постах.

class Tag(Model):
    name = CharField(max_length=50)

class Post(Model):
    # ... попередні поля ...
    tags = ManyToManyField(Tag)

Чому результат такий: Тут немає поля tags у таблиці постів. І немає поля posts у таблиці тегів. Система створила невидиму таблицю зв'язків. Це дозволяє нам додавати скільки завгодно тегів, не ламаючи структуру.


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

Прийшов час забруднити руки кодом. Уявіть, що ви будуєте онлайн-магазин.

Завдання 1: Основа Опишіть модель Product (Товар). Які поля їй потрібні? (Підказка: назва, ціна, опис, чи є в наявності).

Завдання 2: Категоризація (One-to-Many) Створіть модель Category (наприклад, "Електроніка", "Одяг"). Додайте зв'язок так, щоб один товар належав одній категорії, але в категорії було багато товарів. Де буде прописаний ForeignKey — у Товарі чи в Категорії?

Завдання 3: Виправ помилку Студент написав такий код для системи курсів:

class Student(Model):
    name = CharField()
    courses_list = TextField() # Тут він пише: "Math, History, Physics"

Чому це погано? Як це переписати, використовуючи правильний тип зв'язку?

Завдання 4: Міні-кейс "Spotify" У вас є Song (Пісня) і Playlist (Плейлист). Який зв'язок між ними? (Подумайте: чи може одна пісня бути в різних плейлистах?)

Завдання 5: А що, якщо... Що станеться, якщо у завданні №2 ми видалимо категорію "Електроніка", а у нас є 1000 товарів у ній? Який параметр on_delete ви б обрали, щоб не втратити товари, а просто зробити їх "Без категорії"?


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

Як відрізнити новачка від профі, дивлячись на їхні моделі?

  1. SSOT (Single Source of Truth): Новачок дублює дані ("збережу ім'я автора і в таблиці авторів, і в таблиці книг про всяк випадок"). Профі знає: дані мають зберігатися в одному місці. Якщо треба ім'я — ми "підтягнемо" його через зв'язок.

  2. Типи даних мають значення: Новачок зберігає ціну як текст ("100$"). Профі зберігає як Decimal, щоб потім можна було робити математику (знижки, податки) без болю.

  3. Неймінг: Погано: class Table1, поле data. Добре: class Order, поле created_at. Код читають люди, а не тільки машини. Називайте речі своїми іменами!


6. 🧩 Підсумок

Сьогодні ви зробили великий крок від простого зберігання даних до архітектури даних.

  • Ми навчилися розбивати сутності на окремі таблиці (Моделі).
  • Ми зрозуміли, як пов'язувати їх ниточками (Foreign Keys), щоб не дублювати інформацію.
  • Ми дізналися, що база даних — це не просто склад, а розумний організм, який дбає про порядок.

Що далі? Тепер у нас є красива структура. Але як з неї дістати дані? Як запитати: "Дай мені всі товари з категорії 'Ноутбуки', дешевші за 1000 доларів, відсортовані за датою"?

На наступному уроці ми зануримось у ORM Queries (Запити) — мистецтво ставити правильні питання.

До зустрічі! 🚀