I have found a few questions that are similar to mine, but most of them are dated, or too (or too little) verbose to be helpful.
I have a model like this:
class Breakfast(models.Model):
count_eggs = models.IntegerField()
count_bacon = models.IntegerField()
had_toast = models.BooleanField()
Now, in building a RESTful API, I need the ability to sort Breakfast objects by the total of count_eggs + count_bacon
without storing this permanently on the model.
Many of the current and popular questions suggest something like this:
Breakfast.objects.extra(
select={'total_food':'count_eggs + count_bacon'},
order_by=('total_food',)
)
This seems to work for many, but Django docs appear to dissuade this solution. So, in the 1.10+ world, What is the best/correct way to do this type of filtering on the sum of two (or more) fields in Django
By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model's Meta . You can override this on a per- QuerySet basis by using the order_by method. The result above will be ordered by pub_date descending, then by headline ascending.
When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.
Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.
You should use annotate, I got an example of mine and adapted to your case, try this:
from django.db.models import F, Sum
Breakfast.objects.all().\
annotate(total_food=Sum(
F('count_eggs ') + F('count_bacon'))
).\
order_by('total_food')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With