36👍
It isn’t possible to order by the result of the calculated_total
method.
However, you can set the default ordering for your model admin by overriding the get_queryset
method for your model admin, and ordering by an expression that calculates the same thing.
class OrderModelAdmin(admin.ModelAdmin):
...
def get_queryset(self, request):
qs = super(OrderModelAdmin, self).get_queryset(request)
qs = qs.order_by(F('cost')*F('quantity'))
return qs
A similar approach is to annotate the queryset with the total, and then order by that field. Assuming that cost is a DecimalField
and quantity is an IntegerField
, you need to use ExpressionWrapper
to set the output field. See the docs on Using F() with annotations for more info.
I don’t think it’s possible to use total
directly in list_display
. However, you can alter your calculated_total
method to access the annotated field. We set calculated_total.admin_order_field = 'total'
so that the Django admin allows you to sort on that column by clicking on it.
from django.db.models import F, ExpressionWrapper, DecimalField
class OrderModelAdmin(admin.ModelAdmin):
list_display = ['name', 'number', 'price', 'calculated_total']
def calculated_total(self, obj):
return obj.total
calculated_total.admin_order_field = 'total'
def get_queryset(self, request):
qs = super(OrderModelAdmin, self).get_queryset(request)
qs = qs.annotate(total=ExpressionWrapper(F('cost')*F('quantity'), output_field=DecimalField())).order_by('total')
return qs