django admin включить сортировку для вычисляемых полей



У меня есть следующие два поля в моей таблице БД и модели (имя модели: порядок):



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 Admin?

844   1  

1 ответ:

Невозможно упорядочить по результату метода 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

Аналогичный подход заключается в том, чтобы аннотировать набор запросов суммой, а затем упорядочить по этому полю. Предполагая, что стоимость - это 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

Comments

    Ничего не найдено.