JavaRush /Курси /Модуль 3: Django /Фільтрація з використанням F-об'єктів

Фільтрація з використанням F-об'єктів

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

Сьогодні на порядку денному — F-об'єкти. Вони дозволяють звертатися до полів моделі "як є" на рівні бази даних. Ми навчимося використовувати їх для створення ефективних запитів, щоб не витягувати дані в Python тільки для простих операцій.

Що таке F-об'єкти?

F-об'єкти — це інструмент із модуля django.db.models, який надає можливість напряму працювати з полями моделі в рамках SQL-запитів. Це зручно для виконання операцій між полями одного або кількох записів без необхідності витягувати дані в Python-код, обробляти їх, а потім відправляти зміни назад у базу.

Тобто, F-об'єкти допомагають перенести логіку обчислень із Python у саму базу даних, зберігаючи запит атомарним (хвала ACID-парадигмі!). Це не лише робить код чистішим, але й значно підвищує продуктивність застосунку.

Для чого потрібні F-об'єкти? Уявіть, що ми створюємо інтернет-магазин. Для оновлення інформації, наприклад, про знижки чи залишки на складі, доводиться витягувати поточні дані товару, змінювати їх у коді й записувати назад. Якщо б над одним і тим самим товаром працювали кілька користувачів одночасно, то можна було б легко "перезаписати" зміни. Це небезпечно і недобре.

F-об'єкти вирішують цю проблему, дозволяючи змінювати дані прямо на рівні бази даних. Замість "витягни-зміни-збережи" ви просто говорите запиту "додай до цього поля 5". І база сама розбереться з атомарністю та цілісністю даних.

Приклад використання F-об'єктів

Для початку створимо модель товарів для нашого інтернет-магазину:

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField(default=0)  # кількість на складі

    def __str__(self):
        return self.name

Припустимо, у нас є записи в базі даних для товарів:

ID Назва Ціна Залишок
1 Крута клавіатура 4000 10
2 Геймерська миша 2000 5
3 Монітор 4К 20000 3

Приклад 1: зменшення залишку на складі

Припустимо, клієнт купив 1 одиницю товару. Ми хочемо зменшити кількість stock на 1. З Python-підходом це виглядало б так:

from myapp.models import Product

product = Product.objects.get(id=1)
product.stock -= 1  # Зменшуємо залишок
product.save()

З використанням F-об'єктів ми можемо написати більш елегантний та безпечний запит:

from django.db.models import F
from myapp.models import Product

Product.objects.filter(id=1).update(stock=F('stock') - 1)

Що тут відбувається?

  • Ми використовуємо метод update() для масового оновлення записів.
  • Замість конкретного значення для stock використовуємо F-об'єкт, який вказує: "зменши поточне значення поля stock на 1".

Приклад 2: підвищення ціни товарів

Припустимо, ми вирішили підвищити ціну на товари через інфляцію (життя жорстке). Наприклад, збільшити ціну на 10%:

Product.objects.all().update(price=F('price') * 1.1)

База даних автоматично помножить значення поля price на 1.1 для кожного продукту.

І наш оновлений стан:

ID Назва Ціна Залишок
1 Крута клавіатура 4400 10
2 Геймерська миша 2200 5
3 Монітор 4К 22000 3

Особливості застосування F-об'єктів

Операції між полями

F-об'єкти також дозволяють виконувати операції між різними полями однієї моделі. Наприклад, якщо ми хочемо забезпечити знижку тільки для тих товарів, у яких залишок більше 5 штук, і ціна вище 5000:

Product.objects.filter(stock__gt=5, price__gt=5000).update(price=F('price') - F('price') * 0.2)

У цьому запиті:

  1. Ми фільтруємо товари, де stock > 5 і price > 5000.
  2. Зменшуємо ціну на 20% тільки для відповідних товарів.

Складні обчислення

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

Product.objects.update(stock=F('stock') // 2)

Тут // — оператор цілочисельного ділення. У результаті кількість товарів у наявності скоротиться рівно вдвічі.

Типові помилки при використанні F-об'єктів

  1. Спроба оновити значення після його отримання

Якщо ви намагаєтесь виконати щось на кшталт:

product = Product.objects.get(id=1)
product.stock = F('stock') - 1
product.save()

Це не спрацює, тому що F('stock') не може бути використаний для обчислень у Python; він потрібен лише для SQL-запитів. Замість цього використовуйте метод update().

  1. Невідповідність типів даних

Якщо ви спробуєте виконати операцію з несумісними полями (наприклад, скласти рядок і число), Django видасть помилку:

Product.objects.update(stock=F('name') + 1)  # викличе помилку

База даних не зможе обробити такий вираз, оскільки типи даних name (рядок) і 1 (число) несумісні.

Практичне завдання

Уявіть, що ви розробляєте застосунок для управління складом. Спробуйте впоратися з наступними задачами:

  1. Ви створюєте акцію: збільшуєте залишок на складі (поле stock) товарів, у яких залишок менше 10, на 5 одиниць.
  2. Збільшіть ціну всіх товарів на 15%, які коштують менше 5000.
  3. Встановіть залишок на складі кожного товару рівним поточній ціні, поділеній на 100 (цілочисельне ділення).

Напишіть код для виконання цих дій у вашому проєкті.

Де це корисно?

У реальних проєктах F-об'єкти допомагають:

  1. Оновлювати дані без конфліктів у конкурентних середовищах.
  2. Зменшувати кількість запитів до бази і навантаження на сервер.
  3. Прискорювати виконання задач, переносячи обчислення з Python у SQL.

Для управління складом, обробки акцій чи масового оновлення даних F-об'єкти стають справжніми рятівниками розробника!

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