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

Gas*_*sim 8 python django django-admin

我的db表和模型中有以下两个字段(Model Name:Order):

id, branch_id, product_id, cost, quantity, status, ordered_at
Run Code Online (Sandbox Code Playgroud)

我在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')
Run Code Online (Sandbox Code Playgroud)

现在,我想为此字段启用排序.实际上,我需要做的就是在SELECT语句中添加一列:

 SELECT (t.cost * t.quantity) as TOTAL
 ORDER BY TOTAL
Run Code Online (Sandbox Code Playgroud)

有没有办法可以在Django Admin中附加SQL语句进行排序?

Ala*_*air 17

无法通过该calculated_total方法的结果进行排序.

但是,您可以通过覆盖模型管理员的get_queryset方法来设置模型管理员的默认顺序,并通过计算相同事​​物的表达式进行排序.

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
Run Code Online (Sandbox Code Playgroud)

类似的方法是使用total注释查询集,然后按该字段排序.假设成本为a DecimalField且数量为a IntegerField,则需要使用ExpressionWrapper设置输出字段.有关详细信息,请参阅有关使用带注释的F()的文档.

我认为不可能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
Run Code Online (Sandbox Code Playgroud)

  • 我使用了注释,它工作正常并且有意义,但上面的代码需要一些调整。我必须添加 `calculated_total.admin_order_field = 'total'`。事实上,这正是我一直在寻找的。能够添加自定义列并根据该列对该字段进行排序。谢谢你! (2认同)