На попередніх лекціях ми вивчили основні види зв'язків між моделями: OneToOne, ForeignKey і ManyToMany.
Сьогодні ми йдемо далі та зосередимося на тому, як створювати та видаляти об'єкти з використанням цих зв'язків.
🌱 Створення пов'язаних об'єктів
Коли один об'єкт пов'язаний з іншим, часто нам потрібно створити цей пов'язаний об'єкт "на місці" або пов'язати вже існуючий об'єкт. Django надає кілька підходів для роботи з цим, залежно від типу зв'язку.
1. Створення пов'язаних об'єктів з OneToOne
Зв'язок один-до-одного означає, що один об'єкт може бути пов'язаний тільки з одним іншим. Приклад з життя: у кожного користувача може бути тільки один персональний профіль.
Давайте створимо дві моделі: User і Profile.
from django.db import models
class User(models.Model):
username = models.CharField(max_length=100)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField()
Тепер, якщо ми хочемо створити профіль для користувача, ми можемо зробити це наступним чином:
# Створюємо користувача
user = User.objects.create(username="student")
# Створюємо пов'язаний профіль
profile = Profile.objects.create(user=user, bio="Я люблю Django!")
Або при використанні пов'язаного імені related_name:
# Створюємо профіль через зворотний зв'язок
user.profile = Profile(bio="Захоплений учень Django")
user.profile.save()
🛠 Особливість:
Якщо ви спробуєте створити другий профіль для одного і того ж користувача, Django видасть помилку, адже зв'язок OneToOne не допускає дублювання.
2. Створення об'єктів з ForeignKey
Зв'язок "один-до-багатьох" використовується, коли один об'єкт може бути пов'язаний з багатьма іншими. Наприклад, кожен користувач може мати кілька статей.
class Article(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='articles')
title = models.CharField(max_length=200)
Створення статті з вже існуючим автором:
author = User.objects.create(username="author_username")
article = Article.objects.create(author=author, title="Моя перша стаття")
Ми також можемо додати статтю через зворотний зв'язок:
# Використовуємо related_name для додавання статті
author.articles.create(title="Друга стаття")
🛠 Примітка:
Якщо related_name не задано, за замовчуванням буде використовуватися <ім'я_моделі>_set:
author.article_set.create(title="Третя стаття")
3. Створення об'єктів з ManyToMany
Зв'язок "багато-до-багатьох" ідеально підходить для випадків, коли об'єкти можуть бути пов'язані з кількома іншими. Наприклад, студенти відвідують курси, і кожен курс має багато студентів.
class Course(models.Model):
name = models.CharField(max_length=200)
class Student(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(Course, related_name='students')
Створення об'єктів та зв'язування їх:
# Створюємо студента і курс
student = Student.objects.create(name="Alice")
course = Course.objects.create(name="Django Masterclass")
# Зв'язуємо їх
student.courses.add(course)
Ми також можемо одразу зв'язати об'єкт при його створенні:
# Створюємо курс і одразу зв'язуємо з існуючим студентом
new_course = Course.objects.create(name="Python Basics")
student.courses.add(new_course)
# Або створюємо студента і прив'язуємо до курсу
course.students.create(name="Bob")
🛠 Особливість:
метод add() підтримує множинні додавання:
student.courses.add(course1, course2, course3)
🗑 Видалення пов'язаних об'єктів
Видалення пов'язане з питанням: "А що робити із залежними об'єктами?". Відповідь Django — це вибір поведінки через on_delete для ForeignKey і OneToOneField.
1. Видалення об'єктів з OneToOne
Якщо користувач видаляється, логічно, що профіль теж має бути видалений. Це ми задаємо за допомогою on_delete=models.CASCADE.
Приклад:
# Видалимо користувача
user.delete()
# Профіль буде автоматично видалений
Ми також можемо вручну видалити профіль:
profile.delete()
2. Видалення об'єктів з ForeignKey
Уявіть, що ми видаляємо автора статті. Що має статися? Встановлене значення on_delete визначає поведінку:
CASCADE— статті автора будуть видалені.SET_NULL— автор для статті станеNULL.
# Якщо автор видалений, пов'язані статті теж видаляються
author.delete()
Якщо ви використовуєте SET_NULL, вам потрібно дозволити значення NULL для поля author:
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
Тепер, при видаленні автора, статті залишаться:
author.delete()
# Статті залишаться, але поле author стане NULL
3. Видалення об'єктів з ManyToMany
Видалення елементів із зв'язку виконується за допомогою методів remove() і clear().
# Видалення конкретного курсу у студента
student.courses.remove(course)
# Видалення всіх курсів студента
student.courses.clear()
🛠 Особливості: якщо ви видаляєте курс або студента, Django автоматично видаляє записи в проміжній таблиці student_courses.
🔨 Практична частина: створюємо навчальний додаток
Уявіть, що ми моделюємо додаток для бібліотек. У нас є такі сутності:
Book(Книга)Author(Автор)Reader(Читач)
Зв'язки:
- Один автор написав багато книг
ForeignKey. - Одна книга може бути прочитана багатьма читачами, а читачі читають багато книг
ManyToMany.
Моделі:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
class Reader(models.Model):
name = models.CharField(max_length=100)
books_read = models.ManyToManyField(Book, related_name='readers')
Спробуйте виконати такі кроки:
- Створіть автора та кілька книг, пов'язаних із ним.
- Створіть читача та зв'яжіть його з кількома книгами.
- Видаліть автора та подивіться, що станеться з книгами.
- Переконайтеся, як працює видалення книг із зв'язку з читачем.
# Приклад:
author = Author.objects.create(name="J.K. Rowling")
book1 = Book.objects.create(title="Harry Potter and the Philosopher's Stone", author=author)
book2 = Book.objects.create(title="Harry Potter and the Chamber of Secrets", author=author)
reader = Reader.objects.create(name="John Doe")
reader.books_read.add(book1, book2)
# Видаляємо автора
author.delete()
# Перевіряємо зв'язок із книгами
print(Reader.objects.get(name="John Doe").books_read.all()) # книги залишаться
Тепер ви вмієте не тільки створювати зв'язки, але й керувати ними у реальних проектах. Django ORM робить це максимально зручним! 😉
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ