Comment afficher dans un template le nombre de visiteurs en ligne sous Django ?

Published: 12 mai 2019

DMCA.com Protection Status

Exemple de solution pour afficher dans un template le nombre de visiteurs en ligne pour un site développé avec Django

Sauvegarder les visiteurs dans une table

On peut tout d'abord dans le fichier models.py ajouter la table suivante:

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

Editer le fichier processor.py

On peut ensuite éditer le fichier 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}

On peut alors ajouter les lignes suivantes

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

On ajoute dans la table Visitor_Infos si le visteur arrive sur une nouvelle 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()

si le visiteur revient sur une page deja visitée on met a jour la date:

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()

dans le fichier settings.py ajouter la ligne 'myapp.processor.save_visitor_infos' (remplacer myapp par le nom de votre 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',
            ],
        },
    },
]

Retrouver le nombre de visiteurs en ligne

Pour retrouver le nombre de visiteurs en ligne on peut regarder le nombre de visiteurs actifs ces 5 dernières minutes par exemple:

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: on utilise la fonction distinct pour éviter les duplications

Afficher le nombre de visiteurs dans un template

Il suffit d'ajouter alors la ligne suivante dans un template quelconque:

{{context_nb_vistors}}

Fichier processor.py complet

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}

Références