django admin启用对计算字段的排序

时间:2017-03-07 22:42:29

标签: python django django-admin

我的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语句进行排序?

1 个答案:

答案 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