When a user logs in some details are saved to the session, lets say using key='user_settings'
When some updates happens within the system I need to loop through all users and delete the 'user_settings' key from each users session. That way I will trigger loading the details fresh from the database.
How can I loop through all sessions and remove the key from each of the sessions?
Looping
Even if your site has only a few thousand users, you might find that the django_sessions table has a few million entries in it. This happens if the sessions haven't been cleaned up. If you loop through them and delete the session entries you will find the process to be very slow. Even 100 sessions would result in a 100 queries being executed.
Using the Session Model.
You can apply filters on django.contrib.sessions.models.Session just as you would on any other model. Thus the following query would clear out all the sessions in one go.
from django.contrib.sessions.models import Session
Session.objects.all().delete()
You could choose to leave out some users
Session.objects.filter(session_key__in = [ ... ]).delete()
It does not involve a data retrieval or looping.
./manage.py
You could also use ./manage.py clearsessions to clean up expired sessions. Unexpired ones will be retained.
At the database level
Perhaps the fasted is to delete all the sessions is with an sql query. Where as retrieval and delete will be very very slow and involves millions of queries.
In the case of databases that support TRUNCATE
TRUNCATE django_session
For those that don't
DELETE FROM django_session
Lastly bear in mind that sessions do expire from time to time, so there isn't a lot of harm in clearing an entire session object instead of just deleting a specific key
You can access and update session data via the SessionStore object:
from django.contrib.sessions.models import Session, SessionStore
for session in Session.objects.all():
store = SessionStore(session.session_key)
del store['user_settings']
store.save()
You can delete the key from the session like any other dictionary.
del request.session['your key']
for more info check this out
How do I delete a session key in Django after it is used once?
Related
I'm developing a small website with Flask & Flask-Login. I need an admin view to monitor all user's online status. I added an is-online column in user db collection and try to update it. But I didn't find any callbacks to handle session expires. How to solve it or any better idea?
Thanks!
FYI, Counting Online Users with Redis | Flask (A Python Microframework) - http://flask.pocoo.org/snippets/71/.
You could get away with checking if users last activity time is bigger(older) than session life time.
if that's the case, you will go on an update their is_online status.
the way i have handled the problem in my application was, since i had a last_activity field in db for each user, to log when they have done what they have done, i could check that value vs session life time.
One very crude method is to create a separate stack that pushes and pops when a user logs in. Assuming that session id and userid on your db is not tied together (i.e., you have separate session id and user id), you can maintain a ledger of sorts and push and pop as sessions are created and destroyed.
You will have to put special emphasis on users running multiple sessions on multiple devices...which is why i put a caveat saying this is a rather crude method.
I'm currently running a Django application with SESSION_ENGINE configured as django.contrib.sessions.backends.db. I'd like to change this to django.contrib.sessions.backends.cached_db for a performance boost.
Can I make this change without destroying the existing sessions?
Yes, you can make this change without logged in users suddenly finding themselves being logged out. That's because cached_db checks memcache first for the key and if it cannot be found in it, goes to the database. Thus making this change will not cause a loss of session data. Fragment of code from cached_db
def load(self):
try:
data = self._cache.get(self.cache_key)
except Exception:
# Some backends (e.g. memcache) raise an exception on invalid
# cache keys. If this happens, reset the session. See #17810.
data = None
if data is None:
# Duplicate DBStore.load, because we need to keep track
# of the expiry date to set it properly in the cache.
However please note that cached sessions backends are a bit over rated. Depending on the middleware that you have, the session object may be updated very often, as often as every request if only to change the expire date. In that case you will find that the database is being written to all the time. Which means the cached value has to be discarded too.
You should be able to. cached_db backend is just a write-through cache to a database backed, persistent, db backend which speeds up your read queries. It will not speed up your write queries, so you should try and find out how much you are reading and writing the session data.
Your Django SECRET_KEY setting determines your session key hashing parametrs along with Session settings that determine the cache you will use for sessions and session your TTLs, so if you are not changing those variables, you should be good.
In Django, is it possible to clean a session variable periodically without cleaning whole session?
Depending upon the session manager, it might be possible but difficult.
If you are using database backed sessions, you could scan the table, parse the base64 encoded data and delete the variable you want cleaned.
If you must do this, I would either extend the sessions system with a custom mod or store the variable independently somewhere I could easily flush it.
Two Approaches
set_expiry time of session and deleting it periodically can be helpful
SESSION_COOKIE_AGE = 5 * 60 #session expiry time (5 mins)
another way as Rob suggested, playing with session data based on session key.
from django.contrib.sessions.models import Session
from django.contrib.sessions.backends.db import SessionStore
sessionid = Session.objects.get(session_key=123f4b3106c740c1a54970a8b611111)
session_data = sessionid.get_decoded()
I need to push changes to my app's session scopes in real time. Each user in session in my app has a similar struct to this:
session.user =
{
name = "Foo",
mojo = "100"
};
Users can modify each others' "mojo." For example, if user Foo received 10 mojo points, and he now has 110, I need to update his session.user.mojo to reflect the additional "mojo" received. I need to modify his session struct, in other words.
Example 2: User in session 1 does something where user in session 2 receives "mojo." The session.user.mojo in session 2 needs to be updated to reflect this change.
Some info:
The inital mojo value is pulled from the database and stored in the session when a user logs in.
"Mojo" updates always take place in the database. "Mojo" stored in the session is used to govern user privileges.
What are my options? Is this even possible? I have absolutely no idea on how to do something like that.
UPDATE I don't want pass the updated values back to the user (the data will refresh when the user navigates between pages). I only want to change them in the appropriate user's session scope.
This answer is ColdFusion 9 specific.
Cache user data (e.g. cachePut()) by user ID, and keep track of their user ID in session. Every update to mojo should retrieve the user data in cache - if present - and update it there as well. Finally, if this is a multi-server environment, setup messaging between the machines that broadcasts the user ID of any change to mojo, servers receiving the message then update their own cached user data.
What this buys you is limiting the amount of database activity that goes on, pretty good liveness, and makes the mojo value available globally, which has the added benefit of being available for purposes other than the user session (e.g. another user can review their profile to see the mojo score).
If you really need to change vars in a particular Session, there's no built-in way to do that. Maybe you can abstract out the logic, instead of accessing the mojo from Session, always access mojo from DB?
update: Why session? How about a big struct in Application scope, and use userID or sessionID as key, and mojo as value? You can also store a timestape like lastUpdated and delete the ones that has not been updated to reclaim your memory. Then from time to time, update your DB? Or... update your DB async if u're worry about performance.
I need to track some information on users, but would like to retain it for a fixed time period, say a week.
If I set this value via request.sessions, and the user logs out, can I retrieve it if they log back in later? This all assumes that my sessions are normally set to expire in 30 days, if the user neVer logs out.
While thinking about the above problem, I decided to store the data in a table, but I would still like to know the answer to above for referenCe. I also decided not to use cookies due to unreliability.
It would depend on your session backend. But the default backend (backends.db) does delete the row from the sessions table when you log out.
I would recommend adding the data to a field in the user profile. Using the session will give problems even if you don't delete the data. The next time the user logs in you won't know which session id he/she used the last time and normally you only have the session id to look up. Not a user id so you can get all sessions owned by a specific user.