django:将查询集保存到会话

django:将查询集保存到会话,django,django-queryset,django-sessions,django-cache,Django,Django Queryset,Django Sessions,Django Cache,我试图将在一个视图中获得的查询结果保存到会话中,并在另一个视图中检索它,因此我尝试了如下操作: def default (request): equipment_list = Equipment.objects.all() request.session['export_querset'] = equipment_list 然而,这给了我 TypeError at /calbase/ <QuerySet [<Equipment: A>, <Equip

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

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
TypeError位于/calbase/
JSON不可序列化

我想知道这到底意味着什么,我该怎么做?或者除了使用session之外,可能还有其他方法来完成我想要的任务?

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

要保存查询集,可以使用valuesvalues\u list方法获取所需字段,然后将它们强制转换到列表中,然后将列表保存到会话中。(不过,大部分时间只保存PKs来完成任务)

所以基本上:

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))

最好更改保存此特殊结果(值列表)的方式,以便进行更好的查找,字典可能是一个不错的选择。

如果您正在保存此结果:

 equipment_list = Equipment.objects.all()
您不应该也不需要使用会话。为什么?因为这是一个没有任何过滤的简单查询。设备清单对所有用户都是通用的。这可以很容易地保存在缓存中

 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
序列化,而是使用酸洗。

'e4c5'引起了一个完全有效的问题。从有限的代码中我们可以看到,将该查询的结果放入会话中是没有意义的。当然,除非你们有一些我们在这里看不到的其他计划。我将忽略这一点,并假设您必须将查询结果保存到会话中

根据这个假设,您必须理解Django提供给您的queryset实例是一个python对象。您可以在Django应用程序中轻松地移动它。但是,每当您尝试通过线路将此类实体发送到其他数据存储/应用程序(在您的情况下,将其保存到会话中,这涉及将此数据发送到您配置的会话存储)时,它必须可序列化为以下某种格式:

  • 您的应用程序知道如何将对象序列化为
  • 另一端的数据存储知道如何反序列化。在本例中,接受的格式似乎是JSON。(这是可选的,JSON字符串可以直接存储)
  • 问题是,queryset实例不仅包含从表返回的行,还包含一系列其他属性和元属性,这些属性和元属性在使用Django ORM API时非常方便。当您尝试通过连接将queryset实例发送到会话存储时,系统不会有更好的了解,并尝试将所有这些属性序列化为JSON。这会失败,因为queryset中存在无法序列化为JSON的属性

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


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

    在django中保存查询集需要将其序列化,这会导致错误。通过将查询集保存在会话中轻松移动查询集的一种方法是列出设备模型的id。(或用作模型主键的任何其他字段),例如:

    然后,每当你需要这些设备时,遍历这个列表并获得相应的设备

            equipments = [Equipment.objects.get(id=id) for id in request.session['export_querset']]
    

    注意:此方法效率低下,不建议用于大型查询集,但对于小型查询集,可以放心使用。

    您只能在会话中存储json可序列化对象,如数组、int或字符串。。。也许在您的情况下,在会话中存储id/pk就足够了?*-“无法保存”@dwightgunning抱歉不理解您的评论我的坏。。。我不确定您关于在缓存中存储QS而不首先将其转换为值(序列化)的说明是否正确?如何在我的应用程序中移动此python对象?@arijeet将查询集的结果从一个视图传递到另一个视图还有什么可能?
            equipments = [Equipment.objects.get(id=id) for id in request.session['export_querset']]