Наша мета — навчитися оновлювати і видаляти записи у базі даних. Це надзвичайно важливо, оскільки дані рідко залишаються незмінними: користувачі оновлюють профілі, додають і видаляють пости, закладки та ще купу всього. І все це ви зможете робити на льоту за допомогою Django ORM.
Оновлення записів: основи
Оновлення даних — це повсякденне завдання для будь-якого додатка. Наприклад, припустимо, у нас є модель Book, і нам потрібно оновити назву книги або рік її публікації. Давайте спочатку подивимося, як це робиться.
Ось приклад нашої моделі, яку ми будемо використовувати в цій лекції:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_year = models.IntegerField()
def __str__(self):
return f"{self.title} by {self.author}"
Оновлення об'єкта
Щоб оновити запис, ми спочатку повинні знайти її в базі даних. Після цього просто змінюємо параметри об'єкта і викликаємо метод .save().
from myapp.models import Book
# Знайдемо книгу, яку хочемо оновити
book = Book.objects.get(id=1)
# Змінимо її назву
book.title = "Нова назва книги"
book.published_year = 2023
# Збережемо зміни
book.save()
print(f"Книга оновлена: {book.title}, {book.published_year}")
Коли ви викликаєте метод save(), Django автоматично формує SQL-запит UPDATE, щоб змінити відповідний запис у базі даних.
Оновлення множини записів
Іноді потрібно оновити відразу кілька записів. Наприклад, потрібно встановити новий рік публікації для всіх книг певного автора. Django ORM надає для цієї мети метод update().
# Оновимо рік публікації для всіх книг автора "Толстой"
Book.objects.filter(author="Толстой").update(published_year=2022)
print("Усі книги автора 'Толстой' оновлені!")
Метод update() виконує один SQL-запит, тому це набагато швидше, ніж оновлення кожного запису через save() у циклі. Більше того, метод update() не викликає сигнал save(), що теж потрібно враховувати у складних проєктах.
Особливості оновлення даних
При оновленні даних варто враховувати кілька важливих моментів:
- Перевірка існування запису: якщо ви використовуєте метод
.get(), а запис не знайдено, Django викине виключенняDoesNotExist. Тому не забувайте використовуватиtry-exceptабо перевіряти існування запису за допомогою методу.exists().
try:
book = Book.objects.get(id=99) # Пробуємо знайти запис
book.title = "Помилка 404"
book.save()
except Book.DoesNotExist:
print("Книга з таким ID не знайдена!")
Ліниве завантаження QuerySet: Django ORM економить ресурси завдяки лінивому завантаженню даних. Поки ви не намагаєтесь використовувати об'єкти з QuerySet, SQL-запит не виконується. Це потрібно враховувати при виконанні масових операцій.
Перезапис даних: при виклику
save()Django оновлює всі поля моделі. Якщо ви використовуєте методupdate(), він модифікує тільки зазначені вами поля.
Видалення записів
Тепер перейдемо до наступного завдання — видалення записів. Наприклад, користувач може видалити пост у блозі, і цей запис має бути видалений з бази даних.
Видалення одного об'єкта
Щоб видалити один запис, використовується метод .delete().
# Знайдемо книгу і видалимо її
book = Book.objects.get(id=1)
book.delete()
print("Книгу видалено!")
Тут Django формує SQL-запит DELETE і видаляє запис із бази даних. Важливо зазначити, що метод .delete() викликає сигнали pre_delete і post_delete, що може бути корисним для виконання додаткових дій.
Видалення кількох записів
Якщо потрібно видалити кілька записів, можна використати метод filter() разом із delete().
# Видалимо всі книги автора "Безіменний автор"
Book.objects.filter(author="Безіменний автор").delete()
print("Усі книги 'Безіменного автора' видалено!")
Подібно до методу update(), метод delete() для QuerySet виконує один SQL-запит, що робить його набагато швидшим, ніж видалення записів через цикл.
Видалення всіх записів
Чи є у вас бажання "трохи похуліганити"? Тоді ось як можна видалити всі записи з таблиці:
# Видаляємо абсолютно всі книги
Book.objects.all().delete()
print("Зібрання бібліотеки видалено. Сподіваюся, це не було випадковістю.")
Але будьте обережні з цим кодом! Це дія незворотна. Якщо ви випадково видалите всі записи, відновити їх можна буде тільки з бекапу, якщо він у вас є.
Застереження та типові помилки
Як і у випадку з оновленням даних, робота з видаленням записів вимагає особливої обережності:
Перевірка існування записів: перед видаленням переконайтеся, що записи дійсно існують, інакше виклик
delete()може нічого не зробити (що, звісно, не викличе помилку, але може заплутати).Каскадне видалення: якщо у вас у моделі є зовнішні ключі (
ForeignKey), видалення запису може призвести до каскадного видалення пов'язаних об'єктів. Цю поведінку можна налаштувати за допомогою атрибутаon_deleteу поліForeignKey.
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)
# Видалення автора призведе до видалення всіх його книг
- Журнали дій: у продакшені замість прямого видалення часто використовується концепція "м'якого видалення" (soft delete). Це означає, що запис залишається в базі даних, але позначається як видалений. Це зручно для аудиту та відновлення даних.
class Book(models.Model):
title = models.CharField(max_length=200)
is_deleted = models.BooleanField(default=False)
def delete(self):
self.is_deleted = True
self.save()
Практичне завдання
Завдання 1: Оновлення записів
- Додайте у вашу модель
Bookнове полеgenre(жанр книги) з типомCharField. - За допомогою Django shell оновіть жанр для всіх книг автора "Пушкін" на "Класика".
- Перевірте оновлення, отримавши всі книги цього автора.
Завдання 2: Видалення записів
- Видаліть всі книги, у яких рік публікації менше 2000.
- Реалізуйте "м'яке видалення" для моделі
Book. Для цього додайте полеis_deletedі змініть логіку методуdelete().
Тепер ви вмієте оновлювати та видаляти записи у базі даних за допомогою Django ORM. Ці навички знадобляться вам не лише у навчальних проєктах, але й у реальних додатках, де дані постійно змінюються. З таким інструментарієм ви вже готові до наступних етапів роботи з Django.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ