首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >django:将查询集保存到会话

django:将查询集保存到会话
EN

Stack Overflow用户
提问于 2016-09-06 20:51:19
回答 4查看 6.3K关注 0票数 4

我试图将在一个视图中获得的查询结果保存到会话中,然后在另一个视图中检索它,因此我尝试了如下所示:

代码语言:javascript
复制
def default (request):
    equipment_list = Equipment.objects.all()

    request.session['export_querset'] = equipment_list

然而,这给了我

代码语言:javascript
复制
TypeError at /calbase/

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

我想知道这到底意味着什么,我该如何去做呢?或者,除了使用会话之外,还有其他方法来做我想做的事情?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-09-07 06:33:30

“e4c5”引发了一种完全正确的担忧。从有限的代码中可以看到,将查询的结果放入会话中是没有意义的。当然,除非你还有其他的计划,我们在这里看不见。我将忽略这一点,并假设您绝对必须将查询结果保存到会话中。

有了这个假设,您必须理解Django给您的queryset实例是一个python对象。您可以在Django应用程序中移动它,而不会遇到任何麻烦。但是,每当您试图通过线路将这样的实体发送到其他数据存储区/应用程序(在您的示例中,将其保存到会话中,这涉及将此数据发送到您配置的会话存储区)时,它必须可序列化为以下格式:

  1. 您的应用程序知道如何将对象序列化为
  2. 另一端的数据存储知道如何反序列化.在本例中,可接受的格式似乎是JSON。(这是可选的,可以直接存储JSON字符串)

问题是,queryset实例不仅包含从表中返回的行,还包含一些其他属性和元属性,这些属性和元属性在使用Django ORM时对您很有用。当您试图通过线路将queryset实例发送到您的会话存储时,系统对此一无所知,并试图将所有这些属性序列化为JSON。这会失败,因为queryset中有一些属性不能序列化为JSON。

就解决方案而言,如果您必须像一些人建议的那样将数据保存到会话中,那么简单地执行objects.all().values()并将其保存到会话中可能并不总是有效的。一个简单的例子是,当表返回datetime对象时。Datetime对象在默认情况下是可序列化的,而不是JSON序列化的。

那你该怎么办?您需要的是某种类型的序列化程序,它接受一个查询集,并安全地遍历返回的行,将每个python原生数据类型转换为一个JSON安全等效的数据类型,然后返回它。对于datetime.datetime对象,需要调用obj.isoformat()将其转换为ISO格式的日期时间字符串。

票数 4
EN

Stack Overflow用户

发布于 2016-09-07 06:19:28

如果这就是你要保存的东西:

代码语言:javascript
复制
 equipment_list = Equipment.objects.all()

您不应该也不需要使用会话。为什么?因为这是一个没有任何过滤的简单查询。equipment_list对于所有用户来说都是通用的。这可以很容易地保存在缓存中。

代码语言:javascript
复制
 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)

请注意,查询集可以保存在缓存中,而不必首先将其转换为值。

更新:

其他答案之一提到,查询集不是json可序列化的。只有当您试图将其作为json响应传递出去时,这才适用。当您试图缓存它时不适用,因为django.core.cache不使用json序列化,而是使用泡菜。

票数 7
EN

Stack Overflow用户

发布于 2016-09-06 21:00:20

您不能在会话中保存QuerySet实例,因为正如您所说的,它们不是JSON。有关更多信息,请阅读

为了保存查询集,您可以使用valuesvalues_list方法来获取所需的字段,然后将它们转换为一个列表,然后将列表保存到会话中。

所以基本上:

代码语言:javascript
复制
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)的方式也更好,这样您就可以有更好的查找,字典可能是一个不错的选择。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39357646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档