我的db表和模型中有以下两个字段(Model Name:Order):
id, branch_id, product_id, cost, quantity, status, ordered_at
我在OrderModelAdmin中有以下代码:
list_display = (
'order_number',
'branch',
'product',
'cost',
'quantity',
'calculated_total',
'status',
'ordered_at',
)
def calculated_total(self, obj):
return obj.cost * obj.quantity
calculated_total.short_description = _('Total')
现在,我想为此字段启用排序。实际上,我需要做的就是在SELECT语句中添加一列:
SELECT (t.cost * t.quantity) as TOTAL
ORDER BY TOTAL
有没有办法可以在Django Admin中附加SQL语句进行排序?
答案 0 :(得分:13)
无法通过calculated_total
方法的结果进行排序。
但是,您可以通过覆盖模型管理员的get_queryset
方法和计算相同内容的ordering by an expression来设置模型管理员的默认顺序。
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
类似的方法是使用total注释查询集,然后按该字段排序。假设费用为DecimalField
且数量为IntegerField
,则需要使用ExpressionWrapper
来设置输出字段。有关详细信息,请参阅Using F() with annotations上的文档。
我认为不可能直接在total
中使用list_display
。但是,您可以更改calculated_total
方法以访问带注释的字段。我们设置calculated_total.admin_order_field = 'total'
,以便Django管理员允许您通过单击对该列进行排序。
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