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-объекты становятся настоящими спасателями разработчика!

1
Задача
Модуль 3: Django, 10 уровень, 6 лекция
Недоступна
Увеличение количества товаров в базе данных
Увеличение количества товаров в базе данных
1
Задача
Модуль 3: Django, 10 уровень, 6 лекция
Недоступна
Фильтрация объектов по сравнению полей
Фильтрация объектов по сравнению полей
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ