2016-09-06 14 views
2

我想保存查詢結果在一個視圖中的會話獲得,而在另一種觀點認爲檢索它,所以我嘗試類似如下:Django的:保存查詢設置爲會話

def default (request): 
    equipment_list = Equipment.objects.all() 

    request.session['export_querset'] = equipment_list 

然而,這給我

TypeError at /calbase/ 

<QuerySet [<Equipment: A>, <Equipment: B>, <Equipment: C>]> is not JSON serializable 

我想知道這是什麼意思,我應該怎麼去呢?或者,除了使用會話之外,還有其他方法可以做我想做的事情?

+0

你只能在會話中存儲json可序列化的對象,比如數組,int或者一個字符串...也許在你的情況下,它足以存儲會話中的id/pk? – RodrigoDela

回答

2

'e4c5'引發了一個完全有效的問題。從我們可以看到的有限代碼中,將該查詢的結果放入會話中是沒有意義的。除非你有其他一些我們無法在這裏看到的計劃。我會忽略這一點,並假定絕對必須將查詢結果保存到會話中。

有了這個假設,你必須明白Django給你的queryset實例是一個python對象。你可以在你的Django應用程序中移動它,而不會有任何麻煩。但是,每當你試圖通過網絡發送這樣一個實體到其他數據存儲/應用程序(在你的情況下,將它保存到會話中,這涉及將數據發送到你配置的會話存儲),它必須是可序列化的其格式爲:

  1. 你的應用程序知道如何在另一端對象序列化爲
  2. 數據存儲知道如何反序列化。在這種情況下,接受的格式似乎是JSON。(這是可選的,JSON字符串可以直接存儲)

問題是,查詢集實例不僅包含從表返回的行,它還包含一堆其他屬性和元屬性進來當您使用Django ORM API時,方便您使用。當您試圖通過電話將查詢集實例發送到會話存儲區時,系統並不知情,並嘗試將所有這些屬性序列化爲JSON。這會失敗,因爲查詢集中的屬性不能序列化爲JSON。

就解決方案而言,如果您必須按照某些人的建議將數據保存到會話中,只需執行objects.all().values()並將其保存到會話中可能並不總是奏效。一個簡單的例子是當你的表返回datetime對象。 Datetime對象是默認的,不是JSON可序列化的。

那麼你應該怎麼做?你需要的是一些接受查詢集的序列化程序,並且安全地遍歷返回的行,將每個python本地數據類型轉換成JSON安全等效,然後返回。在datetime.datetime對象的情況下,您需要調用obj.isoformat()將其轉換爲ISO格式的日期時間字符串。

+0

如何在我的應用程序中移動這個python對象? –

0

您不能在會話中保存QuerySet實例,就像您所說的那樣,它們不是JSON可序列化的。閱讀This瞭解更多信息。

要保存查詢集,您可以使用values_list的方法來獲取所需的字段,然後將它們轉換爲一個列表,然後將列表保存到會話中。(大部分時間只能保存的PK儘管如此)。

所以基本上:

qset = Model.objects.values_list("pk", "field_one", "field_two") # Gives you a ValuesListQuerySet object which's still not serializable. 
cache_results = list(qset) 
# Now you cache the cache_results variable however you want. 
redis.setex("cached:user_id:querytype", 10 * 60, json.dumps(cache_results)) 

這也是更好地改變你保存這個特殊結果的方式(values_list),所以你可以有更好的查找,字典可能是一個不錯的選擇。

3

如果這是您要保存:

equipment_list = Equipment.objects.all() 

你不應該或不需要使用的會話。爲什麼?因爲這是一個沒有任何過濾的簡單查詢。 equipment_list對所有用戶來說都是通用的。這可以很容易地被保存在緩存

from django.core.cache import cache 

equipment_list = cache.get('equipment_list') 
if not equipment_list: 
    equipment_list = Equipment.objects.all() 
    cache.set('equipment_list',equipment_list) 

需要注意的是一個QuerySet 可以沒有它不必先轉換爲值保存在緩存中。

更新:
其中一個答案提到,querysets不是json可序列化的。這隻適用於當您試圖將該關閉作爲json響應傳遞時。當您試圖緩存它時不適用,因爲django.core.cache不使用json序列化它使用酸洗。

+0

* - 「無法保存」? –

+0

@dwightgunning抱歉,不理解您的評論 – e4c5

+0

我的不好...我不確定是否有關將QS存儲在高速緩存中而不首先將其轉換爲值(序列化)的說明是正確的?可以將 –