Mi scuso per aver "fatto" una domanda a cui già conosco la risposta, ma questo è stato abbastanza frustrante che ho pensato che la risposta dovesse essere registrata sullo stackoverflow. Se qualcuno ha qualcosa da aggiungere alla mia spiegazione, assegnerò la "risposta". Non sono riuscito a trovare la risposta cercando in base al problema, ma dopo aver cercato in base alla risposta ho scoperto che il mio "problema" è documented behavior. Risulta anche another person had this problem.
Si scopre che SessionBase è un oggetto simile ai dizionari che tiene traccia di quando si modifica è chiavi, e imposta manualmente un attributo modified
(c'è anche un accessed
). Se si scherza con gli oggetti all'interno di quelle chiavi, tuttavia, SessionBase non ha modo di sapere che gli oggetti sono stati modificati e pertanto le modifiche potrebbero non essere memorizzate in qualsiasi backend che si sta utilizzando. (Sto usando un back-end del database, presumo che questo problema si applichi a tutti i backend, però.) Questo problema potrebbe non essere applicabile ai modelli, poiché il backend probabilmente sta memorizzando un riferimento al modello (e quindi riceverebbe eventuali modifiche quando è caricato il modello dal database), ma il problema si applica ai dizionari (e forse a qualsiasi altro tipo di python di base che deve essere memorizzato interamente nell'archivio delle sessioni.)
Il trucco è che ogni volta che si modificano oggetti nella sessione, il sessione non si nota, è necessario indicare esplicitamente la sessione che si è modificata:
>>> request.session.modified = True
Spero che questo aiuti qualcuno.
Il modo in cui ho ottenuto intorno a questo è stato quello di incapsulare le azioni pop sulla sessione in un metodo che si prende cura dei dettagli (questo metodo accetta anche un parametro di visualizzazione in modo che le variabili di sessione possono essere specifiche per view):
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
Non posso credere di aver appena speso un'ora e mezzo prima di trovare questa domanda. Grazie per aver posto questa domanda e grazie a tutte le risposte. Mi hai salvato i nervi e il resto della mia giornata. –