JavaRush /Курси /Модуль 3: Django /Зв'язок ForeignKey: як зв'язати моделі

Зв'язок ForeignKey: як зв'язати моделі

Модуль 3: Django
Рівень 9 , Лекція 2
Відкрита

Сьогодні ми перейдемо до більш поширеного типу зв'язку, який активно використовується в реальних застосунках: зв'язок один-до-багатьох з використанням ForeignKey.

Що таке зв'язок один-до-багатьох?

Уявіть, що у вас є папка з документами. Папка — це "батько", вона може містити багато "дітей" (документів), але кожен документ належить тільки до однієї папки. Це і є відношення один-до-багатьох (One-to-Many).

З точки зору реляційної бази даних, зв'язок один-до-багатьох виглядає так:

  • Один запис у першій таблиці (батько) може бути пов'язаний із кількома записами у другій таблиці (діти).
  • Кожен запис у другій таблиці посилається лише на один запис у першій таблиці.

У Django такий зв'язок реалізується за допомогою поля ForeignKey.

Коли використовувати зв'язок ForeignKey?

ForeignKey є найбільш часто використовуваним типом зв'язку, який чудово підходить у наступних сценаріях:

  1. Магазин і його товари: один магазин може продавати багато продуктів, але кожен продукт належить одному магазину.
  2. Статті та автори: один автор може написати багато статей, але кожна стаття написана одним автором.
  3. Категорії та продукти: одна категорія може містити багато продуктів, але кожен продукт належить лише одній категорії.

Реалізація зв'язку один-до-багатьох через ForeignKey

Давайте реалізуємо простий приклад. Уявімо, що у нас є система управління блогом, яка складається з двох моделей: Author та Post. Один автор може написати багато постів.

Крок 1: створюємо моделі

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()

    def __str__(self):
        return self.name


class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

Розберемо код:

  1. Модель Author:

    • Містить ім'я name та email email автора.
    • Поле __str__ повертає ім'я автора для зручного відображення.
  2. Модель Post:

    • Містить заголовок title, контент content та посилання на автора через поле author.
    • Поле author використовує ForeignKey, вказуючи на модель Author.
  3. Ключовий параметр у ForeignKeyon_delete:

    • Тут ми вказали on_delete=models.CASCADE, що означає: якщо запис батьківської таблиці Author видаляється, то всі пов'язані пости Post також будуть автоматично видалені.

Крок 2: виконуємо міграції

Після опису моделей необхідно зробити міграції, щоб зміни вступили в силу в базі даних.

python manage.py makemigrations
python manage.py migrate

Крок 3: додаємо дані

Тепер давайте створимо кілька авторів та постів у Django shell.

python manage.py shell
# Імпортуємо наші моделі
from blog.models import Author, Post

# Створюємо авторів
author_1 = Author.objects.create(name="Іван Іванов", email="ivan@example.com")
author_2 = Author.objects.create(name="Анна Смирнова", email="anna@example.com")

# Створюємо пости
post_1 = Post.objects.create(title="Перша стаття", content="Зміст статті 1", author=author_1)
post_2 = Post.objects.create(title="Друга стаття", content="Зміст статті 2", author=author_1)
post_3 = Post.objects.create(title="Третя стаття", content="Зміст статті 3", author=author_2)

Тепер у нас є два автори (Іван та Анна) і три пости, які відносяться до них.

Крок 4: робота із записами

Отримання пов'язаних об'єктів. За допомогою ForeignKey ви можете легко витягувати пов'язані записи:

# Отримуємо автора статті
post = Post.objects.get(title="Перша стаття")
print(post.author)  # Виведе: Іван Іванов

# Отримуємо всі статті автора
author = Author.objects.get(name="Іван Іванов")
posts = author.post_set.all()
print(posts)  # Виведе QuerySet з двома статтями
Примітка:

Django автоматично створює related_name у форматі modelname_set (у даному випадку post_set) для зворотного зв'язку.

Створюємо статті через автора

Ви можете створювати статті через модель Author, не вказуючи явно ForeignKey.

author = Author.objects.get(name="Анна Смирнова")
author.post_set.create(title="Четверта стаття", content="Зміст статті 4")

Поведінка при видаленні: on_delete

Важливим моментом при використанні ForeignKey є вказівка поведінки при видаленні пов'язаних об'єктів. Django надає кілька опцій:

  • CASCADE: видаляє всі пов'язані об'єкти (за замовчуванням).
  • SET_NULL: встановлює значення NULL, якщо це дозволено полем.
  • PROTECT: видає помилку, якщо видаляються пов'язані записи.
  • DO_NOTHING: нічого не робить (не рекомендується).
  • SET_DEFAULT: встановлює значення за замовчуванням.

Приклад:

author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True, blank=True)

Приклади бізнес-сценаріїв

  1. Інтернет-магазин:

    • Категорія Category і Товари Product:

      class Category(models.Model):
          name = models.CharField(max_length=100)
      
      class Product(models.Model):
          name = models.CharField(max_length=100)
          category = models.ForeignKey(Category, on_delete=models.CASCADE)
      
  2. Система бронювання:

    • Кімната Room і Бронювання Booking:
      class Room(models.Model):
          number = models.IntegerField()
      
      class Booking(models.Model):
          room = models.ForeignKey(Room, on_delete=models.PROTECT)
          date = models.DateField()

Часті помилки та особливості

  1. Відсутність міграцій:

    • Не забудь зробити міграції після додавання нового поля ForeignKey, інакше база даних не знатиме про твої зміни.
  2. Помилка при видаленні об'єктів:

    • Не вказуй on_delete=DO_NOTHING, якщо не впевнений у наслідках. Це може призвести до порушення цілісності даних.
  3. Зворотній доступ:

    • Якщо не вказати related_name, Django згенерує його автоматично. Але це ім'я може бути незручним. Краще вказувати явно:
      author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="posts")
      
  4. Проблеми з продуктивністю:

    • Використовуй select_related() для оптимізації запитів, якщо тобі потрібно отримати пов'язані дані.

Практичне застосування

Тепер ти знаєш, як організувати зв'язок один-до-багатьох за допомогою ForeignKey у Django. Цей тип зв'язку — основа більшості веб-додатків, від блогів до систем управління замовленнями чи CRM. Чим більше ти працюєш з моделями, тим більше починаєш цінувати гнучкість і потужність ForeignKey.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ