2012-08-07 72 views
0

我有一個簡單的對象過濾器,使用price__ltprice__gt。這適用於我的產品模型上名爲price的屬性,它是一個CharField [字符串](十進制看到相同的錯誤,並導致聚集問題,因此恢復爲字符串)。Django對象過濾器 - 價格行爲奇怪,例如170被視爲17 etc

看來,在這些值傳遞給過濾器時,他們是在一種奇怪的方式處理,如10被視爲100例如:

/products/price/10-200/收益產品售價100-200。過濾器將作爲filterargs傳入:FILTER ARGS: {'price__lt': '200', 'price__gt': '10'}。這也意味着價格/ 0-170不會返回價格爲18.50的產品;它出於某種原因將170視爲「小於18」。

任何想法會導致這種情況,以及如何解決它?謝謝!

+0

你能複製並粘貼相應的urlpattern(來自urls.py)嗎? – aruseni 2012-08-07 10:05:52

+0

快速思考表明,當你交換到charfield時,任何比較都將基於我猜17(0)在18之前出現的字符?我會考慮在運行比較之前將值轉換爲十進制。 – 2012-08-07 10:11:17

+0

我相信url模式是無關緊要的,因爲上面顯示的filterargs輸出{'price_lt':'200','price_gt':'10'}來自views.py中的一個打印內容,在它傳遞給Products之前。 objects.filter(filterargs) – user1568252 2012-08-07 10:17:18

回答

2

正如Jeff所說,問題是價格是CharField,因此使用逐字符串比較邏輯進行比較,即任何以1開頭的任何長度的字符串都將小於任何長度的任何字符串開始2

我很好奇,你具有價格爲IntegerField,因爲這似乎是簡單的解決辦法是有什麼問題,但如果你需要保持價格爲CharField,這裏有一個(哈希)的方式來使查詢工作:

lt = 200 
gt = 10 
qs = Product.objects.extra(select={'int_price': 'cast(price as int)'}, 
          where=['int_price < %s', 'int_price > %s'], 
          params=[lt, gt]) 
qs.all() # the result 

這使用Django的QuerySet類的extra方法,您可以在文檔here中閱讀該方法。簡而言之,它使用SQL的cast表達式計算字符串價格的整數版本,然後使用基於該表達式的整數進行過濾。

+0

謝謝Ghopper。我發現了這個問題:基本上我使用charfield構建了初始模型,然後當我更改爲decimalfield時,我沒有重置應用程序並重建數據庫,因此正如上面所建議的那樣,將小數點移入字符串字段。感謝和抱歉! – user1568252 2012-08-07 13:52:59