How to show in a template the number of online visitors with Django ?

Published: May 14, 2019

DMCA.com Protection Status

An example of solution to display in a template the number of online visitors in a django web site:

Create a table Visitor_Infos

First, create a table in models.py called for example: Visitor_Infos:

class Visitor_Infos(models.Model):
    ip_address = models.GenericIPAddressField()
    page_visited = models.TextField()
    event_date = models.DateTimeField(default=datetime.now)

Edit/create the file processor.py

Edit the context file processor.py:

from django.conf import settings

from .models import Visitor_Infos

import socket
import random

def save_visitor_infos(request):
    context_nb_vistors = 0
    #----- get visitor ip -----#
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')    
    #----- check if ip adress is valid -----#
    try:
        socket.inet_aton(ip)
        ip_valid = True
    except socket.error:
        ip_valid = False
    #----- check if ip adress is valid -----#
    if ip_valid:
        do something

    return {"context_nb_vistors":context_nb_vistors}

Add the following lines

present_date = datetime.datetime.now()
ref_date_1 = present_date - datetime.timedelta(days=1)
ref_date_2 = present_date - datetime.timedelta(days=2)

Add a new table element if the visitor visits a new page:

if Visitor_Infos.objects.filter(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1).count() == 0:
    new_visitor_infos = Visitor_Infos(
    ip_address = ip,
    page_visited = request.path,
    event_date = present_date)          
    new_visitor_infos.save()

Update the date if the visitor come back on the same page:

if Visitor_Infos.objects.filter(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1).count() == 1:
    visitor_infos_obj = Visitor_Infos.objects.get(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1)
    visitor_infos_obj.event_date = present_date
    visitor_infos_obj.save()

in the file settings.py add the line 'myapp.processor.save_visitor_infos' (replace myapp by the name of your application)

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'myapp.processor.save_visitor_infos',
            ],
        },
    },
]

Retrieve the number of visitors:

To retrieve the number of online visitor, we can for example get the number of active visitors the last 5 minutes:

ref_date = present_date - datetime.timedelta(minutes=5) 
context_nb_vistors = Visitor_Infos.objects.filter(event_date__gte=ref_date).values_list('ip_address', flat=True).distinct().count()
return {"context_nb_vistors":context_nb_vistors}

Note: the function distinct() has been used to removed the duplicate

Show the number of visitors

Finally, just add in any template:

{{context_nb_vistors}}

processor.py file

from django.conf import settings

from .models import Visitor_Infos

import socket
import random

def save_visitor_infos(request):
    try:
        #----- get visitor ip -----#
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')    
        #----- check if ip adress is valid -----#
        try:
            socket.inet_aton(ip)
            ip_valid = True
        except socket.error:
            ip_valid = False
        #----- check if ip adress is valid -----#
        if ip_valid:

            present_date = datetime.datetime.now()
            ref_date_1 = present_date - datetime.timedelta(days=1)
            ref_date_2 = present_date - datetime.timedelta(days=2)

            if Visitor_Infos.objects.filter(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1).count() == 0:
                new_visitor_infos = Visitor_Infos(
                ip_address = ip,
                page_visited = request.path,
                event_date = present_date)          
                new_visitor_infos.save()

            if Visitor_Infos.objects.filter(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1).count() == 1:
                visitor_infos_obj = Visitor_Infos.objects.get(ip_address=ip, page_visited=request.path, event_date__gte=ref_date_1)
                visitor_infos_obj.event_date = present_date
                visitor_infos_obj.save()
    except:
        pass

    context_nb_vistors = 0
    ref_date = present_date - datetime.timedelta(minutes=5) 
    context_nb_vistors = Visitor_Infos.objects.filter(event_date__gte=ref_date).values_list('ip_address', flat=True).distinct().count()

    return {"context_nb_vistors":context_nb_vistors}

References