Search code examples
djangodjango-templatesdjango-sessions

How to check whether a user is online in django template?


In template, when I use

{% if topic.creator.is_authenticated %}
Online
{% else %}
Offline
{% endif %}

the users turn out to be always online, even when they has signed out a while ago. So I'm wondering how to check the online users correctly?


Solution

  • ‌Thanks this excellent blog post, with slight modifications, I came up with a better solution, which uses memcache, hence less delay per request:

    in models.py add:

    from django.core.cache import cache 
    import datetime
    from myproject import settings
    

    and add these method the userprofile class:

    def last_seen(self):
        return cache.get('seen_%s' % self.user.username)
    
    def online(self):
        if self.last_seen():
            now = datetime.datetime.now()
            if now > self.last_seen() + datetime.timedelta(
                         seconds=settings.USER_ONLINE_TIMEOUT):
                return False
            else:
                return True
        else:
            return False 
    

    in userprofile folder add this middleware.py

    import datetime
    from django.core.cache import cache
    from django.conf import settings
    
    class ActiveUserMiddleware:
    
        def process_request(self, request):
            current_user = request.user
            if request.user.is_authenticated():
                now = datetime.datetime.now()
                cache.set('seen_%s' % (current_user.username), now, 
                               settings.USER_LASTSEEN_TIMEOUT)
    

    in settings.py add 'userprofile.middleware.ActiveUserMiddleware', to MIDDLEWARE_CLASSES and also add:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': '127.0.0.1:11211',              
            }
        }
    
    # Number of seconds of inactivity before a user is marked offline
    USER_ONLINE_TIMEOUT = 300
    
    # Number of seconds that we will keep track of inactive users for before 
    # their last seen is removed from the cache
    USER_LASTSEEN_TIMEOUT = 60 * 60 * 24 * 7
    

    and in profile.html:

     <table>
       <tr><th>Last Seen</th><td>{% if profile.last_seen %}{{ profile.last_seen|timesince }}{% else %}awhile{% endif %} ago</td></tr>
       <tr><th>Online</th><td>{{ profile.online }}</td></tr>
     </table>
    

    That's it!

    To test cache in the console, to make sure that memcache works fine:

    $memcached -vv
    $ python manage.py shell
    >>> from django.core.cache import cache
    >>> cache.set("foo", "bar")
    >>> cache.get("foo")
    'bar'
    >>> cache.set("foo", "zaq")
    >>> cache.get("foo")
    'zaq'