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