Django管理使分拣计算领域
问题描述:
我有我的数据库表和模型下面的两个字段(型号名称订购):Django管理使分拣计算领域
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
有没有一种方法,我可以追加SQL语句在Django管理排序?
答
无法通过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
一个类似的方法是用总数对查询集进行注释,然后按该字段排序。假设成本为DecimalField
,数量为IntegerField
,则需要使用ExpressionWrapper
来设置输出字段。有关更多信息,请参阅Using F() with annotations上的文档。
我不认为有可能直接在list_display
中使用total
。但是,您可以更改您的calculated_total
方法以访问带注释的字段。我们设置了calculate_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
我用注解,它工作正常,它是有道理的,但上面的代码需要一些调整。我不得不添加'calculated_total.admin_order_field ='total''。实际上,这正是我所期待的。能够添加自定义列并根据该列对该字段进行排序。谢谢! – Gasim
@Gasim好点!默认情况下,我的原始答案按总数排序查询集。如果您想要点击列进行排序,您需要设置“admin_order_field”。我已经添加了答案。 – Alasdair