2016-09-06 71 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存储在高速缓存中而不首先将其转换为值(序列化)的说明是正确的?可以将 –