当前位置: 首页 > 知识库问答 >
问题:

django:将查询集保存到会话

葛勇锐
2023-03-14

我试图将在一个视图中获得的查询结果保存到会话中,并在另一个视图中检索它,所以我尝试了如下方式:

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

我想知道这到底是什么意思,我应该怎么做?或者除了使用会话之外,还有其他方法可以做我想做的事情?

共有3个答案

聂风史
2023-03-14

您不能在会话中保存QuerySet实例,因为正如您所说,它们不是JSON可序列化的。阅读此处了解更多信息。

若要保存查询集,可以使用值和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)的方式,这样可以更好地查找,字典可能是一个不错的选择。

支嘉祥
2023-03-14

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

有了这个假设,你必须明白Django给你的查询集实例是一个python对象。您可以在Django应用程序中轻松移动它。但是,每当您尝试通过网络将此类实体发送到其他数据存储/应用程序(在本例中,将其保存到会话中,这涉及将此数据发送到配置的会话存储),它必须可序列化为某种格式,这些格式:

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

问题是,查询集实例不仅包含从表返回的行,还包含一堆其他属性和元属性,当您使用Django ORM API时,这些属性对您很有用。当您尝试通过网络将查询集实例发送到您的会话存储时,系统不知道更好,并尝试将所有这些属性序列化为JSON。这失败了,因为查询集中有一些属性不能序列化为JSON。

解决方案而言,如果您必须将数据保存到会话中,正如某些人所建议的那样,简单地执行对象.all().values() 并将其保存到会话中可能并不总是有效。一个简单的情况是,您的表返回日期时间对象。默认情况下,日期时间对象是不可序列化的。

那你该怎么办?您需要的是某种序列化程序,它接受queryset,并安全地迭代返回的行,将每个python本机数据类型转换为JSON安全的等价物,然后返回。在<code>日期时间的情况下。对于datetimeobjects,您需要调用obj。isoformat()将其转换为ISO格式的日期时间字符串。

袁良弼
2023-03-14

如果这是您要保存的内容:

 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可以保存在缓存中,而无需先将其转换为值。

更新:
其他答案之一提到查询集不可json序列化。这仅适用于您尝试将其传递为json响应时。当您尝试缓存它时不适用,因为django.core.cache不使用json序列化,它使用酸洗。

 类似资料:
  • 在这一章中,你将学习 Django 如何连接到数据库,并将数据存储在里面。一探究竟吧! QuerySet 是什幺呢? 从本质上说,QuerySet 是给定模型的对象列表(list)。QuerySet 允许您从数据库中读取数据,对其进行筛选以及排序。 用例子来学习最容易的了。让我们试试这个,好吗? Django shell 打开你本地的终端(不是在Python解析器里面) 然后输入这个命令: (my

  • 问题内容: 我有一个带有两个自定义管理器方法的Django模型。每个对象都基于对象的不同属性返回模型对象的不同子集。 有没有什么方法可以获取一个查询集,或者只是一个对象列表,那就是每个管理器方法返回的查询集的并集? 问题答案: 这可以工作,看起来更干净: 如果你不希望重复,则需要添加:

  • 问题内容: 我有点困惑如何使用在Django的。例如,一个对象Blog ,以及与该对象相关的attribute entry_set。是什么意思? 如果有人可以使用此示例显示可能的输出,我将不胜感激。 问题答案: 你看到的是反向相关的对象查找。 在你的示例中: 现在,给定类型为的对象,你将可以访问相关对象-这是一个正向关系。该是一个反向查找类变量的Django为你看跌期权。 因此,给定对象-你将执行

  • 假设我有一个与产品模型具有多对一关系的图像模型,如下所示: 当尝试访问模板中图像标记上的{{product.get_primary_image.url}时,它会输出一个索引器而不是图像,即使在向数据库添加了多个图像之后,我仍然会得到索引错误。我哪里会出错?请帮帮我,我还是个新手。

  • 问题内容: 我正在尝试使用hibernate模式写入多个数据库。我已经将写和读/写会话封装在单个会话对象中。但是,当我去保存时,出现很多错误,这些对象已与另一个会话关联:“非法尝试将一个集合与两个打开的会话关联” 这是我的代码: 我试图逐出该物体并冲洗;但是,这会导致“行被另一个事务更新或删除”问题,即使两个会话都指向不同的数据库。 除了上述内容,我还尝试使用hibernate的复制功能。没有错误