Django order_by sum of fields
Question:
Is it possible to use the django ORM to order a queryset by the sum of two different fields?
For example, I have a model that looks like this:
class Component(models.Model):
material_cost = CostField()
labor_cost = CostField()
and I want to do something like this:
component = Component.objects.order_by(F('material_cost') + F('labor_cost'))[0]
But unfortunately, F objects don’t seem to work with ‘order_by’. Is such a thing possible with django?
Answers:
You can use extra
for this.
Component.objects.extra(
select={'fieldsum':'material_cost + labor_cost'},
order_by=('fieldsum',)
)
See the documentation.
Use extra:
Component.objects.extra(select = {'total_cost' : 'material_cost + labor_cost'},
order_by = ['total_cost',])[0]
I think it’s time to provide better answer. Since django team is considering deprecating extra(), it’s better to use annotate()
with F()
expression:
from django.db.models import F
Component.objects.annotate(fieldsum=F('material_cost') + F('labor_cost')).order_by('fieldsum')
You can use F()
expression directly in order_by
now, your suggested code should work:
component = Component.objects.order_by(F('material_cost') + F('labor_cost'))
Is it possible to use the django ORM to order a queryset by the sum of two different fields?
For example, I have a model that looks like this:
class Component(models.Model):
material_cost = CostField()
labor_cost = CostField()
and I want to do something like this:
component = Component.objects.order_by(F('material_cost') + F('labor_cost'))[0]
But unfortunately, F objects don’t seem to work with ‘order_by’. Is such a thing possible with django?
You can use extra
for this.
Component.objects.extra(
select={'fieldsum':'material_cost + labor_cost'},
order_by=('fieldsum',)
)
See the documentation.
Use extra:
Component.objects.extra(select = {'total_cost' : 'material_cost + labor_cost'},
order_by = ['total_cost',])[0]
I think it’s time to provide better answer. Since django team is considering deprecating extra(), it’s better to use annotate()
with F()
expression:
from django.db.models import F
Component.objects.annotate(fieldsum=F('material_cost') + F('labor_cost')).order_by('fieldsum')
You can use F()
expression directly in order_by
now, your suggested code should work:
component = Component.objects.order_by(F('material_cost') + F('labor_cost'))