2017-09-14 102 views
0

有一段代碼,它從DB中提取一些QuerySet,然後將新計算的字段附加到查詢集中的每個對象。這不是通過註釋添加此字段的選項(因爲它是遺留的,因爲此計算基於另一個已預先獲取的數據)。通過動態添加字段重新排序Django QuerySet

像這樣:

from django.db import models 
class Human(models.Model): 
    name = models.CharField() 
    surname = models.CharField() 

def calculate_new_field(s): 
    return len(s.name)*42 

people = Human.objects.filter(id__in=[1,2,3,4,5]) 

for s in people: 
    s.new_column = calculate_new_field(s) 
# people.somehow_reorder(new_order_by=new_column) 

所以現在的QuerySet所有的人都有一個新列。我想通過new_column字段來訂購這些對象。因爲它是一個數據庫選項,所以order_by()不會工作。我明白我可以將它們作爲一個排序列表傳遞,但是有很多模板和其他邏輯,期望從這個對象的QuerySet類似於它的方法等等。

所以問題是:是否有一些不是非常糟糕和骯髒的方式來重新排序現有的QuerySet通過dinamically添加字段或使用此數據創建新的類似於QuerySet的對象?我相信我不是唯一一個遇到這個問題的人,而且它已經通過django解決了。但我找不到任何東西(除了添加第三方庫,這也不是一個選項)。

回答

0

你可以嘗試functions.Length

from django.db.models.functions import Length 

qs = Human.objects.filter(id__in=[1,2,3,4,5]) 
qs.annotate(reorder=Length('name') * 42).order_by('reorder') 
+0

其實我不是按長度排列,它是一個計算的百分比。我只是用長短的方式來誣衊那個添加的列基本上只是一個計算得出的數字。對不起,如果我錯過了你。 – Paul

+0

,正如你可以看到你可以添加計算來註釋和使用它的順序,嘗試顯示你的真實代碼 –

0

從概念上講,查詢集是不結果的列表,但「指令來得到這些結果。」這是懶惰的評估,也緩存。保持緩存結果的QuerySet的內部屬性是qs._result_cache

因此,for s in people句子強制對查詢進行評估並緩存結果。

你可以得知後,結果做排序:

people._result_cache.sort(key=attrgetter('new_column'))

但是,評價一個QuerySet後,就沒有什麼意義(在我看來),以保持QuerySet的接口,因爲許多操作將導致重新評估查詢。從這一點上,你應該處理的模型列表