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
Liens | Site |
---|---|
Remove duplicates in a django query | stackoverflow |
Django: remove duplicates (group by) from queryset by related model field | stackoverflow |
Exclude Duplicate Objects in django queryset | stackoverflow |
The use of HTTP_X_FORWARDED_FOR and REMOTE_ADDR i | programering |
How to Get a Client IP Address in DJANGO | pressthered |