Issue
Prologue:
This is a question arising often in SO:
- Subtracting two annotated columns
- Django query with simple arithmetic among model fields and comparison with field from another model
- Django Aggregation: Summation of Multiplication of two fields
And can also be applied here:
I have composed an example on SO Documentation but since the Documentation will get shut down on August 8, 2017, I will follow the suggestion of this widely upvoted and discussed meta answer and transform my example to a self-answered post.
Of course, I would be more than happy to see any different approach as well!!
Question:
Assume the following model:
class MyModel(models.Model):
number_1 = models.IntegerField()
number_2 = models.IntegerField()
date_1 = models.DateTimeField()
date_2 = models.DateTimeField()
How can I execute arithmetic operations between fields of this model?
For example, how can I find:
- The product of
number_1
andnumber_2
of a MyModel object? - How to filter items where
date_2
is 10 or more days older thandate_1
?
Solution
F()
expressions can be used to execute arithmetic operations (+
, -
, *
etc.) among model fields, in order to define an algebraic lookup/connection between them.
An
F()
object represents the value of a model field or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
let's tackle the issues then:
The product of two fields:
result = MyModel.objects.all().annotate(prod=F('number_1') * F('number_2'))
Now every item in
result
has an extra column named 'prod' which contains the product ofnumber_1
andnumber_2
of each item respectively.Filter by day difference:
from datetime import timedelta result = MyModel.objects.all().annotate( delta=F('date_2') - F('date_1') ).filter(delta__gte=timedelta(days=10))
Now the items in
result
are those fromMyModel
whosedate_2
is 10 or more days older thandate_1
. These items have a new column nameddelta
with that difference.A different case:
We can even use
F()
expressions to make arithmetic operations on annotated columns as follows:result = MyModel.objects.all() .annotate(sum_1=Sum('number_1')) .annotate(sum_2=Sum('number_2')) .annotate(sum_diff=F('sum_2') - F('sum_1'))
Answered By - John Moutafis
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.