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
Links | 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 |