Subscribe to our YouTube Channel!
[Jul 12, 2021] New Video: How to Use Django Rest Framework Permissions (DRF Tutorial - Part 7)


Django Tips #13 Using F() Expressions

Django Tips #13 Using F() Expressions

In the Django QuerySet API, F() expressions are used to refer to model field values directly in the database. Let’s say you have a Product class with a price field, and you want to increase the price of all products in 20%.

A possible solution would be:

products = Product.objects.all() for product in products: product.price *= 1.2 product.save()

Instead you could use an F() expression to update it in a single query:

from django.db.models import F Product.objects.update(price=F('price') * 1.2)

You can also do it for a single object:

product = Product.objects.get(pk=5009) product.price = F('price') * 1.2 product.save()

But take care with this kind of assignment. The F() object persist after saving the model.

product.price # price = Decimal('10.00') product.price = F('price') + 1 product.save() # price = Decimal('11.00') product.name = 'What the F()' product.save() # price = Decimal('12.00')

So, basically after updating a field like that, product.price will hold an instance of django.db.models.expressions.CombinedExpression, instead of the actual result. If you want to access the result immediately:

product.price = F('price') + 1 product.save() print(product.price) # <CombinedExpression: F(price) + Value(1)> product.refresh_from_db() print(product.price) # Decimal('13.00')

You can also use it to annotate data:

from django.db.models import ExpressionWrapper, DecimalField Product.objects.all().annotate( value_in_stock=ExpressionWrapper( F('price') * F('stock'), output_field=DecimalField() ) )

Since price is a DecimalField and stock is a IntegerField, we need to wrap the expression inside a ExpressionWrapper object.

It can be used to filter data as well:

Product.objects.filter(stock__gte=F('ordered'))