在Django会话中修改字典不会修改会话

我在string键引用的会话中存储字典:

>>> request.session['my_dict'] = {'a': 1, 'b': 2, 'c': 3} 

我遇到的问题是,当我直接修改字典时,在下一个请求期间值不会被改变:

 >>> request.session['my_dict'].pop('c') 3 >>> request.session.has_key('c') False # looks okay... ... # Next request >>> request.session.has_key('c') True # what gives! 

正如 文档所述 ,另一种select是使用

 SESSION_SAVE_EVERY_REQUEST=True 

这将使每个请求都发生这种情况。 如果在你的代码中发生这种情况,可能是值得的; 我猜偶尔有额外的开销不会太多,而且远远低于忽略包含这个潜在问题的潜在问题

 request.session.modified = True 

每一行。

我很抱歉“询问”了一个我已经知道答案的问题,但是这令人沮丧,我以为答案应该logging在计算器上。 如果有人有什么补充我的解释,我将奖励“答案”。 我找不到根据问题find答案,但根据答案search后,我发现我的“问题”是logging的行为 。 另外原来另一个人有这个问题 。

事实certificate,SessionBase是一个类似于字典的对象,用于跟踪修改键的时间,以及手动设置modified的属性(还有一个accessed )。 但是,如果你使用这些键中的对象,SessionBase无法知道这些对象是否被修改,因此你的改变可能不会被存储在你使用的任何后端。 (我使用的是数据库后端,但我认为这个问题也适用于所有的后端)。这个问题可能不适用于模型,因为后端可能存储了对模型的引用(因此在加载时会收到任何更改来自数据库的模型),但是这个问题确实适用于字典(也可能是任何其他必须完全存储在会话存储中的基本pythontypes)。

诀窍是,无论何时修改会话中不会注意到的会话中的对象,都必须明确地告诉会话它已被修改:

 >>> request.session.modified = True 

希望这有助于某人。

我解决这个问题的方法是将会话中的任何popup操作封装到处理细节的方法中(该方法还接受视图参数,以便会话variables可以是特定于视图的):

 def session_pop(request, view, key, *args, **kwargs): """ Either returns and removes the value of the key from request.session, or, if request.session[key] is a list, returns the result of a pop on this list. Also, if view is not None, only looks within request.session[view.func_name] so that I can store view-specific session variables. """ # figure out which dictionary we want to operate on. dicto = {} if view is None: dicto = request.session else: if request.session.has_key(view.func_name): dicto = request.session[view.func_name] if dicto.has_key(key): # This is redundant if `dicto == request.session`, but rather than # duplicate the logic to test whether we popped a list underneath # the root level of the session, (which is also determined by `view`) # just explicitly set `modified` # since we certainly modified the session here. request.session.modified = True # Return a non-list if not type(dicto[key]) == type(list()): return dicto.pop(key) # pop a list else: if len(dicto[key]) > 0: return dicto[key].pop() # Parse out a default from the args/kwargs if len(args) > 0: default = args[0] elif kwargs.has_key('default'): default = kwargs['default'] else: # If there wasn't one, complain raise KeyError('Session does not have key "{0}" and no default was provided'.format(key)) return default 

我对此并不感到惊讶。 我想这就像修改一个元组的内容一样:

 a = (1,[2],3) print a >>> 1, [2], 3) a[1] = 4 >>> Traceback (most recent call last): ... File "<stdin>", line 1, in <module> ... TypeError: 'tuple' object does not support item assignment print a >>> 1, [2], 3) a[1][0] = 4 print a >>> 1, [4], 3) 

不过谢谢。