Files
2026-01-07 12:09:20 +05:30

94 lines
4.4 KiB
Python
Executable File

from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from at_django_boilerplate.utils.mixins import UUIDMixin
class SessionConsentModel(UUIDMixin):
session_id = models.CharField(max_length=255, unique=True)
accept_all_consent_received = models.BooleanField(default=False)
essential_only_consent_received = models.BooleanField(default=False)
received_on = models.DateTimeField(auto_now_add=True)
@property
def consent_received(self):
return self.accept_all_consent_received or self.essential_only_consent_received
class VisitorModel(UUIDMixin):
visiter_number = models.IntegerField()
session_id = models.CharField(max_length=255)
def __str__(self):
return f'#{self.visiter_number}'
class PageVisit(UUIDMixin):
user = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, null=True, blank=True)
session_id = models.CharField(max_length=255)
visitor = models.ForeignKey(VisitorModel,related_name='page_visits',null=True,blank=True ,on_delete=models.SET_NULL)
url = models.CharField(max_length=255)
ip_address = models.CharField(max_length=45) # Supports IPv4 and IPv6
query_params = models.TextField(blank=True, null=True)
timestamp = models.DateTimeField(default=timezone.now)
path = models.CharField(max_length=512)
user_agent = models.TextField(blank=True, null=True)
session_data = models.JSONField(default=dict, blank=True, null=True) # Keep this field
location = models.CharField(max_length=64,null=True,blank=True)
country = models.CharField(max_length=64,null=True,blank=True)
latitude=models.CharField(max_length=64,null=True,blank=True)
longitude=models.CharField(max_length=64,null=True,blank=True)
is_new_user = models.BooleanField(default=True)
referrer = models.CharField(max_length=512, blank=True, null=True)
visit_count = models.PositiveIntegerField(default=1,null=True,blank=True)
entered_at = models.DateTimeField(auto_now_add=True,null=True,blank=True)
exited_at = models.DateTimeField(null=True, blank=True)
time_spent_seconds = models.PositiveIntegerField(default=0,null=True,blank=True)
class Meta:
ordering = ['-timestamp']
indexes = [
models.Index(fields=['session_id', 'timestamp']),
]
def __str__(self):
return f"{self.user.email if self.user else 'Anonymous'} visited {self.url} at {self.timestamp}"
def save(self, *args, **kwargs):
# Detect if this is a new user
if self.user and PageVisit.objects.filter(user=self.user).exists():
self.is_new_user = False
super().save(*args, **kwargs)
def calculate_time_spent(self):
if self.exited_at:
self.time_spent_seconds = int(
(self.exited_at - self.entered_at).total_seconds()
)
class DailyUserStats(UUIDMixin):
date = models.DateField(unique=True,null=True,blank=True)
new_users = models.PositiveIntegerField(null=True,blank=True)
returning_users = models.PositiveIntegerField(null=True,blank=True)
created_at = models.DateTimeField(auto_now_add=True,null=True,blank=True)
class VisitorSession(UUIDMixin):
session_id = models.CharField(max_length=255, unique=True,null=True,blank=True)
visitor = models.ForeignKey(VisitorModel, on_delete=models.SET_NULL, null=True, blank=True)
is_bounce = models.BooleanField(default=False,null=True,blank=True)
started_at = models.DateTimeField(auto_now_add=True,null=True,blank=True)
ended_at = models.DateTimeField(null=True, blank=True)
duration_seconds = models.PositiveIntegerField(default=0,null=True,blank=True)
def calculate_duration(self):
if self.ended_at:
self.duration_seconds = int(
(self.ended_at - self.started_at).total_seconds()
)
class ClickEvent(UUIDMixin):
session = models.ForeignKey(VisitorSession, on_delete=models.SET_NULL, related_name="clicks",null=True,blank=True)
visitor = models.ForeignKey(VisitorModel, on_delete=models.SET_NULL, null=True, blank=True)
page_path = models.CharField(max_length=512,null=True,blank=True)
element_text = models.CharField(max_length=255,null=True,blank=True)
element_type = models.CharField(max_length=50,null=True,blank=True)
timestamp = models.DateTimeField(auto_now_add=True,null=True,blank=True)