2017-03-07 75 views
2

我有我的數據庫表和模型下面的兩個字段(型號名稱訂購):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管理排序?

回答

5

無法通過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 
+0

我用註解,它工作正常,它是有道理的,但上面的代碼需要一些調整。我不得不添加'calculated_total.admin_order_field ='total''。實際上,這正是我所期待的。能夠添加自定義列並根據該列對該字段進行排序。謝謝! – Gasim

+0

@Gasim好點!默認情況下,我的原始答案按總數排序查詢集。如果您想要點擊列進行排序,您需要設置「admin_order_field」。我已經添加了答案。 – Alasdair