Класс F
Класс F из модуля django.db.models представляет собой выражение, которое ссылается на поле модели или аннотированное значение. Основное назначение класса - выполнение операций сравнения и арифметических действий непосредственно в базе данных, минуя этап загрузки объектов в память Python. Это позволяет избежать состояния гонки при конкурентных обновлениях и значительно повышает производительность. Объекты F могут использоваться в методах filter, exclude, annotate, update, а также в агрегациях и сортировках.
Синтаксис
from 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. Найдем товары, цена которых больше количества:
from 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)
Результат выполнения кода:
"Smartphone 1200 500"
"Laptop 2500 1500"
Пример
Используем F для обновления значения поля относительно текущего значения. Увеличим количество просмотров у статей на 1:
from 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")
Результат выполнения кода:
"Views updated successfully"
Пример
Класс F также позволяет выполнять арифметические операции с несколькими полями модели. Добавим в запрос аннотацию total_price, которая рассчитывается как произведение цены на количество:
from 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)
Результат выполнения кода:
"Smartphone 600000"
"Laptop 3750000"
Пример
Используем F для фильтрации записей с использованием нескольких условий. Найдем статьи, у которых количество комментариев больше, чем лайков:
from 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)
Результат выполнения кода:
"Post about Django"
"Post about Python"
Пример
Класс F можно использовать вместе с агрегациями для выполнения вычислений над значениями полей. Найдем общую стоимость всех товаров на складе:
from 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)
Результат выполнения кода:
"{'total_value': 4350000}"