Класс F

Класс F из модуля django.db.models представляет собой выражение, которое ссылается на поле модели или аннотированное значение. Основное назначение класса - выполнение операций сравнения и арифметических действий непосредственно в базе данных, минуя этап загрузки объектов в память Python. Это позволяет избежать состояния гонки при конкурентных обновлениях и значительно повышает производительность. Объекты F могут использоваться в методах filter, exclude, annotate, update, а также в агрегациях и сортировках.

Синтаксис

pythonfrom django.db.models import F

# Создание выражения для поля
F('field_name')

# Использование в запросах
Model.objects.filter(field1__gt=F('field2'))
Model.objects.annotate(total=F('price') * F('quantity'))
Model.objects.update(views=F('views') + 1)

Пример

Рассмотрим модель Product с полями price и quantity. Найдем товары, цена которых больше количества:

pythonfrom django.db import models
from django.db.models import F

class Product(models.Model):
  name = models.CharField(max_length=100)
  price = models.IntegerField()
  quantity = models.IntegerField()

# Products where price > quantity
res = Product.objects.filter(price__gt=F('quantity'))
for product in res:
  print(product.name, product.price, product.quantity)

Результат выполнения кода:

python"Smartphone 1200 500"
"Laptop 2500 1500"

Пример

Используем F для обновления значения поля относительно текущего значения. Увеличим количество просмотров у статей на 1:

pythonfrom django.db import models
from django.db.models import F

class Article(models.Model):
  title = models.CharField(max_length=200)
  views = models.IntegerField(default=0)

# Increase views by 1 for all articles
Article.objects.update(views=F('views') + 1)
print("Views updated successfully")

Результат выполнения кода:

python"Views updated successfully"

Пример

Класс F также позволяет выполнять арифметические операции с несколькими полями модели. Добавим в запрос аннотацию total_price, которая рассчитывается как произведение цены на количество:

pythonfrom django.db import models
from django.db.models import F

class Product(models.Model):
  name = models.CharField(max_length=100)
  price = models.IntegerField()
  quantity = models.IntegerField()

# Annotate each product with total price
products = Product.objects.annotate(total_price=F('price') * F('quantity'))
for product in products:
  print(product.name, product.total_price)

Результат выполнения кода:

python"Smartphone 600000"
"Laptop 3750000"

Пример

Используем F для фильтрации записей с использованием нескольких условий. Найдем статьи, у которых количество комментариев больше, чем лайков:

pythonfrom django.db import models
from django.db.models import F

class Post(models.Model):
  title = models.CharField(max_length=200)
  comments = models.IntegerField()
  likes = models.IntegerField()

# Posts where comments > likes
res = Post.objects.filter(comments__gt=F('likes'))
for post in res:
  print(post.title)

Результат выполнения кода:

python"Post about Django"
"Post about Python"

Пример

Класс F можно использовать вместе с агрегациями для выполнения вычислений над значениями полей. Найдем общую стоимость всех товаров на складе:

pythonfrom django.db import models
from django.db.models import F, Sum

class Product(models.Model):
  name = models.CharField(max_length=100)
  price = models.IntegerField()
  quantity = models.IntegerField()

# Calculate total inventory value
total_value = Product.objects.aggregate(
  total_value=Sum(F('price') * F('quantity'))
)
print(total_value)

Результат выполнения кода:

python"{'total_value': 4350000}"

Смотрите также

  • класс Q,
    который позволяет создавать сложные условия фильтрации с операторами AND, OR и NOT
  • класс Count,
    который возвращает количество связанных объектов
  • класс Sum,
    который вычисляет сумму значений поля
  • метод annotate,
    который добавляет аннотации к каждому объекту в QuerySet