Commits

Claudio Marinozzi committed 113b166

If the new settings "ONLY_LOGGED_USERS" is True it works like before this
modification, otherwise if False (default) keeps track about anonymous users
too.

Please note that a hit on database is done only when using the template tag
online_users (if ONLY_LOGGED_USERS False). Values may be cached instead.

  • Participants
  • Parent commits 459a911

Comments (0)

Files changed (4)

File online_status/middleware.py

 from django.core.cache import cache
 from online_status.status import refresh_user, refresh_users_list
-from status import OnlineStatus, CACHE_PREFIX_USER
+from status import OnlineStatus, CACHE_PREFIX_USER, CACHE_PREFIX_ANONYM_USER, ONLY_LOGGED_USERS
 
 
 class OnlineStatusMiddleware(object):
     """Cache OnlineStatus instance for an authenticated User"""
     
     def process_request(self, request):
-        if not request.user.is_authenticated():
+        if request.user.is_authenticated():
+            onlinestatus = cache.get(CACHE_PREFIX_USER % request.user.pk)
+        elif not ONLY_LOGGED_USERS:
+            onlinestatus = cache.get(CACHE_PREFIX_ANONYM_USER % request.session.session_key)
+        else :
             return
-        onlinestatus = cache.get(CACHE_PREFIX_USER % request.user.pk)
         if not onlinestatus:
             onlinestatus = OnlineStatus(request)
         refresh_user(request)
-        refresh_users_list(updated=onlinestatus)
+        refresh_users_list(request, updated=onlinestatus)
         return
         

File online_status/status.py

 CACHE_PREFIX_USER = getattr(settings, 'USERS_ONLINE__CACHE_PREFIX_USER', 'online_user') + '_%d'
 CACHE_USERS = getattr(settings, 'USERS_ONLINE__CACHE_USERS', 'online_users')
 
+CACHE_PREFIX_ANONYM_USER = getattr(settings, 'USERS_ONLINE__CACHE_PREFIX_ANONYM_USER', 'online_anonym_user') + '_%s'
+
+ONLY_LOGGED_USERS = getattr(settings, 'USERS_ONLINE__ONLY_LOGGED_USERS', False)
 
 class OnlineStatus(object):
     """Online status data which will be later cached"""
     def set_idle(self):
         self.status = 0        
 
-    def set_active(self):
+    def set_active(self, request):
         self.status = 1
-        self.seen = datetime.now() 
+        self.seen = datetime.now()
+        self.session = request.session.session_key #Can change if operating from multiple browsers
+        self.ip = request.META['REMOTE_ADDR'] #Can change if operating from multiple browsers
+        
+    def is_authenticated(self):
+        return self.user.is_authenticated()
         
 
 
 def refresh_user(request):
     """Sets or updates user's online status"""
-    key = CACHE_PREFIX_USER % request.user.pk
+    if request.user.is_authenticated() :
+        key = CACHE_PREFIX_USER % request.user.pk
+    elif not ONLY_LOGGED_USERS :
+        key = CACHE_PREFIX_ANONYM_USER % request.session.session_key
+    else :
+        return
     onlinestatus = cache.get(key)
     if not onlinestatus:
         onlinestatus = OnlineStatus(request)        
     else:
-        onlinestatus.set_active()
+        onlinestatus.set_active(request)
     cache.set(key, onlinestatus, TIME_OFFLINE)
     return onlinestatus
     #self.refresh_users_list(user=self.user)
     
     
-def refresh_users_list(**kwargs):
+def refresh_users_list(request, **kwargs):
     """Updates online users list and their statuses"""
     updated = kwargs.pop('updated', None)
     online_users = cache.get(CACHE_USERS)        
             user = cache.get(CACHE_PREFIX_USER % obj.user.pk)
             user.set_idle()
             cache.set(CACHE_PREFIX_USER % obj.user.pk, user, TIME_OFFLINE)
-        if obj.user == updated.user:
-            obj.set_active()
+        if obj.user == updated.user and updated.is_authenticated(): #It should never find it if it's an anonymous user, but you never know
+            obj.set_active(request)
             obj.seen = datetime.now()    
             updated_found = True
-    if not updated_found:
+    if not updated_found and updated.is_authenticated():
         online_users.append(updated)    
     cache.set(CACHE_USERS, online_users, TIME_OFFLINE)
     

File online_status/templates/online_status/online_users.html

 {% for online in onlineusers %}
 	<dt class="user">{{ online.user.username }}</dt><dd class="status">{{ online.status|status_format:"text" }}</dd>
 {% endfor %}
+</dl>
+<dl class="onlineanonym_users">
+{% for online in onlineanonymusers %}
+	<dt class="user">{{ online.ip }}</dt><dd class="status">{{ online.status|status_format:"text" }}</dd>
+{% endfor %}
 </dl>

File online_status/templatetags/online_status_tags.py

+import datetime
+
+from django.conf import settings
+
 from django import template
 from django.core.cache import cache
-from online_status.status import CACHE_USERS, status_for_user
-
+from online_status.status import CACHE_USERS, CACHE_PREFIX_ANONYM_USER, TIME_OFFLINE, ONLY_LOGGED_USERS, status_for_user
+from django.contrib.sessions.models import Session
+    
 register = template.Library()
 
 
 def online_users(limit=None):
     """Renders a list of OnlineStatus instances"""
     onlineusers = cache.get(CACHE_USERS)
+    onlineanonymusers = None
+    
+    if not ONLY_LOGGED_USERS :
+        now = datetime.datetime.now()
+        sessions = Session.objects.filter(expire_date__gte = now + datetime.timedelta(0, settings.SESSION_COOKIE_AGE - TIME_OFFLINE)).values_list('session_key', flat = True)
+        onlineanonymusers = filter(lambda x : x is not None, [cache.get(CACHE_PREFIX_ANONYM_USER % session_key, None) for session_key in sessions])
+        onlineusers = [item for item in cache.get(CACHE_USERS, []) if item.status in (0, 1) and item.session in sessions]
+        
+        if onlineanonymusers and limit:
+            onlineanonymusers = onlineanonymusers[:limit]
+            
     if onlineusers and limit:
         onlineusers = onlineusers[:limit]
-    return {'onlineusers': onlineusers,}
+    return {'onlineanonymusers': onlineanonymusers,
+            'onlineusers': onlineusers,}
 
 
 @register.inclusion_tag('online_status/user_status.html')