F
expressions provide a way to reference model field values directly in queries, allowing you to perform operations between fields and update fields based on their current values.
Suppose you have a Book
model with a num_pages
field, and you want to increase the number of pages by 10 for all books:
from django.db.models import F
# Increment num_pages by 10 for all books
Book.objects.update(num_pages=F('num_pages') + 10)
F('num_pages') + 10
references the current value of num_pages
and adds 10 to it.Retrieve books where the number of pages is greater than the number of chapters:
# Retrieve books with num_pages greater than num_chapters
books_with_more_pages = Book.objects.filter(num_pages__gt=F('num_chapters'))
F('num_chapters')
references the num_chapters
field for comparison.The annotate()
method allows you to add calculated fields to your QuerySets, enabling you to perform complex aggregations and computations.
Suppose you have a Sales
model with quantity
and price
fields, and you want to calculate the total sales value for each sale:
from django.db.models import F, Sum
# Annotate total sales value for each sale
sales_with_total_value = Sales.objects.annotate(total_value=F('quantity') * F('price'))
F('quantity') * F('price')
calculates the total value of each sale.Conditional expressions (Case
and When
) allow you to create conditional logic in your queries, similar to SQL CASE
statements.
Suppose you have an Employee
model with a salary
field, and you want to give a 10% bonus to employees with a salary above $50,000 and a 5% bonus to others:
from django.db.models import Case, When, F
# Annotate with conditional bonus
employees_with_bonus = Employee.objects.annotate(
bonus=Case(
When(salary__gt=50000, then=F('salary') * 0.10),
default=F('salary') * 0.05,
output_field=models.FloatField(),
)
)
Case
and When
create conditional logic to calculate the bonus based on the salary.Value expressions (Value
) allow you to include literal values in your queries.
Retrieve all authors and annotate them with a literal value:
from django.db.models import Value
# Annotate authors with a literal value
authors_with_status = Author.objects.annotate(status=Value('active', output_field=models.CharField()))
Value('active')
includes the literal value ‘active’ in the query results.You can combine multiple expressions to create complex queries.
Suppose you have an Order
model with quantity
and unit_price
fields, and you want to calculate the total cost for each order and filter orders with a total cost above $100:
from django.db.models import F, Sum, Q
# Calculate total cost and filter orders
orders_with_high_cost = Order.objects.annotate(total_cost=F('quantity') * F('unit_price')).filter(total_cost__gt=100)
F('quantity') * F('unit_price')
calculates the total cost for each order.filter(total_cost__gt=100)
filters orders with a total cost above $100.