Давайте займемося оновленням даних. Якщо створення нових об'єктів схоже на народження немовляти в базі даних, то оновлення — це щось на кшталт "зміни вбрання" або "нової зачіски" для існуючого об'єкта. Ми вивчимо два основних способи оновлення даних: масове оновлення через update() і індивідуальне оновлення полів об'єкта через його методи. Приготуйтеся, це буде цікаво!
Основи оновлення даних
Оновити дані в Django можна двома способами:
- Оновити конкретний об'єкт, змінюючи його поля та зберігаючи зміни.
- Масово оновити записи через метод
update().
Кожен із цих підходів має свої переваги та обмеження. Давайте розглянемо обидва варіанти детальніше.
Індивідуальне оновлення об'єкта
Під час роботи з конкретним об'єктом ми можемо оновити його поля, просто призначивши їм нові значення, а потім викликавши метод .save(). Ось як це виглядає:
from myapp.models import Product
# Припустимо, у нас є продукт із назвою "Молоко"
product = Product.objects.get(name="Молоко")
product.price = 60.99 # Оновлюємо ціну
product.save() # Зберігаємо зміни у базу даних
Зверни увагу, що метод save() обов'язково має бути викликаний, інакше зміни просто не потраплять у базу. Django не буде зберігати об'єкт "автоматично".
Приклад: додавання знижки
Припустимо, у нас є модель Product із полями name та price. Ми хочемо додати знижку в 10% до товару, якщо його ціна перевищує 100:
product = Product.objects.get(name="Смартфон")
if product.price > 100:
product.price *= 0.9 # Віднімаємо 10%
product.save() # Зберігаємо оновлене значення
Масове оновлення даних
Якщо потрібно оновити одразу кілька записів, на допомогу приходить update(). Цей метод оновлює поля всіх записів, що потрапили в QuerySet, в одному SQL-запиті. Це особливо корисно для великих обсягів даних, оскільки він працює швидше, ніж оновлення об'єктів по одному.
Ось як це робиться:
from myapp.models import Product
# Встановлюємо знижку 5% на всі товари, ціна яких вища за 500
Product.objects.filter(price__gt=500).update(discounted=True)
Що відбувається всередині?
Метод update() генерує один SQL-запит, який оновлює всі записи, що відповідають умові. Наприклад, рядок вище буде перетворений у SQL, подібний до цього:
UPDATE your_table_name SET discounted = True WHERE price > 500;
Цей підхід чудово підходить для масових змін, але він не викликає метод save() у об'єктів. Це означає, що жодна додаткова логіка, пов'язана з save(), не буде виконана.
Збереження змін у Django ORM
Після оновлення об'єкта потрібно зберегти зміни в базу даних. У випадку індивідуального об'єкта використовується метод save().
Порядок збереження:
- Знайдіть об'єкт у базі даних за допомогою QuerySet (
get()абоfilter()). - Змініть потрібні поля.
- Викличте метод
save().
Приклад з додаванням опису продукту:
product = Product.objects.get(name="Хліб")
product.description = "М'який і свіжий хліб з пекарні."
product.save()
Якщо ти забудеш викликати .save(), то зміни залишаться тільки на рівні об'єкта в пам'яті і ніяк не відобразяться в базі даних.
Особливості використання update()
Метод update() дозволяє оновлювати відразу декілька об'єктів однією командою. Це робить його швидким і зручним інструментом, особливо для великих обсягів даних.
Приклад масового змінення поля:
# Всі товари дешевше 100 гривень робимо "акційними"
Product.objects.filter(price__lt=100).update(is_promotion=True)
Важливі особливості update():
- Він не викликає метод
save(), відповідно, не виконується додаткова логіка і не спрацьовують сигнали моделі. - Ви не можете використовувати методи моделі у виразі
update(), тільки значення для полів.
Приклад: масове підвищення ціни
Якщо ми хочемо збільшити ціну всіх товарів на 10%, то можемо зробити це з update() і використанням F-об'єктів (про які ми говорили в попередніх лекціях):
from django.db.models import F
# Збільшуємо ціну на 10% для всіх товарів
Product.objects.update(price=F('price') * 1.1)
Цей приклад генерує SQL-запит, який оновлює ціну прямо у базі даних, не завантажуючи об'єкти в пам'ять.
Особливості та підводні камені
Оновлення даних здається простим процесом, але є нюанси, про які варто пам'ятати:
Ледаче завантаження QuerySet: метод
update()працює прямо з QuerySet, не завантажуючи об'єкти в пам'ять. Це добре для продуктивності, але увага до деталей важлива.Не викликається
save(): додаткові перевірки або сигнали, пов'язані з методомsave(), не спрацюють. Якщо вам потрібна така поведінка, оновлюйте записи по одній.Застереження при масовому оновленні: перед викликом
update()переконайтеся, що ваші фільтри достатньо вузькі, щоб випадково не оновити всі записи в таблиці.
Практичне застосування
Припустимо, ми розробляємо інтернет-магазин. Ось кілька практичних прикладів:
Приклад 1: оновлюємо статус замовлення Коли замовлення виконане, ми можемо змінити його статус на "завершено".
from shop.models import Order
order = Order.objects.get(pk=1)
order.status = "Завершено"
order.save()
Приклад 2: масове оновлення
Якщо ми проводимо акцію "Чорна п'ятниця", всі товари отримують знижку 20%:
# Зменшуємо ціну всіх товарів на 20%
from django.db.models import F
Product.objects.update(price=F('price') * 0.8)
Приклад 3: оптимізація через update()
Масове оновлення всіх замовлень, які були відправлені більше тижня тому:
from django.utils.timezone import now
from datetime import timedelta
Order.objects.filter(date_sent__lt=now() - timedelta(days=7)).update(status="Архівовано")
Завершення теми
На цьому етапі ви освоїли навички оновлення даних у Django: від індивідуальної зміни об'єктів і збереження їх через save() до масового оновлення через update(). Вибір методу залежить від контексту і потреб вашого проєкту. На практиці ці знання знадобляться всюди: від зміни інформації про користувачів до управління каталогами продуктів в e-commerce застосунках. Не забувайте експериментувати і тестувати оновлення на запитах, щоб краще розуміти їхній вплив!
У наступній лекції ми продовжимо заглиблюватися в CRUD-операції і дізнаємося, як крім оновлення, видаляти дані з бази безпечно та ефективно.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ