C'est un CW réponse de l'OP réponse originale à cette question (qui a été collé dans la question):
Je m'excuse pour "poser" une question dont je connais déjà la réponse, mais c'était assez frustrant que je pensais que la réponse doit être enregistrée sur stackoverflow. Si quelqu'un a quelque chose à ajouter à mon explication je vais le prix de la "réponse". Je ne pouvais pas trouver la réponse par la recherche basée sur le problème, mais après une recherche basée sur la réponse, j'ai trouvé que mon "problème" est le comportement documenté. S'avère également une autre personne a eu ce problème.
Il s'avère que SessionBase est un objet de type dictionnaire qui garde une trace de quand de le modifier avec les touches, et définit manuellement un attribut modified
(il y a aussi un accessed
). Si vous vous trompez dans les objets à l'intérieur de ces clés, cependant, SessionBase n'a aucun moyen de savoir que les objets sont modifiés, et par conséquent, vos changements ne sont pas stockés dans quel backend vous utilisez. (Je suis en utilisant une base de données backend; je suppose que ce problème s'applique à tous les backends, cependant). Ce problème peut ne pas s'appliquer à des modèles, depuis le backend est probablement stocker une référence du modèle (et donc recevoir tout change quand il chargé le modèle de la base de données), mais le problème ne s'appliquent à des dictionnaires (et peut-être toute autre base de python les types qui doivent être entièrement stockées dans la session magasin.)
Le truc, c'est qu'à chaque fois que vous modifiez des objets à la session et la session ne sera pas un avis, vous devez indiquer explicitement à la session qu'il soit modifié:
>>> request.session.modified = True
Espérons que cela aide quelqu'un.
La façon dont je suis arrivé c'était pour encapsuler toute pop-actions sur la séance, dans une méthode qui prend soin des détails (cette méthode accepte un paramètre affichage de sorte que les variables de session peut être spécifique à la vue):
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