Reputation: 335
I’m trying to set a variable to an expired session out of a view in Django.
I’m aware of django’s documentation on Using sessions out of views. But in my case, I try to set a session variable in a custom management command.
Here’s what I tried :
from django.contrib.sessions.models import Session
class Command(BaseCommand):
help = "My custom command."
def handle(self, *args, **options):
for s in Session.objects.all():
s['my_variable'] = None
What I get is this error:
TypeError: 'Session' object does not support item assignment
I also tried:
[…]
ss = SessionStore(session_key=s.session_key)
ss['my_variable'] = None
ss.save()
This creates another session but does not modify the existing one…
How can I set my_variable
to None
?
Edit: The session I’m trying to set a variable to is expired
Upvotes: 0
Views: 143
Reputation: 335
You can’t do that on expired sessions. Django does not allow you.
But here is a hack:
class Command(BaseCommand):
help = "My custom command."
def handle(self, *args, **options):
future = datetime.datetime(datetime.MAXYEAR, 1, 1)
for s in Session.objects.all():
ed = s.expire_date
s.expire_date = future
s.save()
ss = SessionStore(session_key=s.session_key)
ss['my_variable'] = None
ss.save()
updated_session = Session.objects.get(session_key=s.session_key)
updated_session.expire_date = ed
updated_session.save()
Upvotes: 1
Reputation: 33833
Try this:
from django.contrib.sessions.models import Session
class Command(BaseCommand):
help = "My custom command."
def handle(self, *args, **options):
store_cls = Session.get_session_store_class()
for session in Session.objects.all():
s = store_cls(session.session_key)
s['my_variable'] = None
# so that any subsequent code which reads from the session sees your change
s.save()
The code is loading saved session data from the db, but as Session
model instances.
These are not the same as the session objects you get back from the SessionStore
in the code shown at https://docs.djangoproject.com/en/4.2/topics/http/sessions/#using-sessions-out-of-views
We actually don't really want to deal with Session
model instances at all, what we need is the session_key
from the instance, so that we can instantiate the session store.
We can then update the value in session object via __setitem__
and save it back into the db https://github.com/django/django/blob/main/django/contrib/sessions/backends/db.py#L73 (until we do that our change won't be visible to any other code that tries to read the session data).
Since we only need the session_key
we can amend the code above:
from django.contrib.sessions.models import Session
class Command(BaseCommand):
help = "My custom command."
def handle(self, *args, **options):
store_cls = Session.get_session_store_class()
for session_key in Session.objects.values_list("session_key", flat=True):
s = store_cls(session_key)
s['my_variable'] = None
# so that any subsequent code which reads from the session sees your change
s.save()
Upvotes: 0