На предыдущих лекциях мы изучили основные виды связей между моделями: 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="I love Django!")
Или при использовании связанного имени related_name:
# Создаём профиль через обратную связь
user.profile = Profile(bio="Enthusiastic Django learner")
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="My First Article")
Мы также можем добавить статью через обратную связь:
# Используем related_name для добавления статьи
author.articles.create(title="Second Article")
🛠 Примечание:
Если related_name не задано, по умолчанию будет использоваться <имя_модели>_set:
author.article_set.create(title="Third Article")
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 делает это максимально удобным! 😉
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ