import uuid from django.db import models from django.utils import timezone class ShortLink(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) code = models.CharField(max_length=8, unique=True, db_index=True) target_url = models.URLField(max_length=2048) title = models.CharField(max_length=200, blank=True) created_by_token = models.CharField(max_length=64) external_ref = models.CharField(max_length=64, blank=True, db_index=True) is_active = models.BooleanField(default=True) expires_at = models.DateTimeField(null=True, blank=True) click_count = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["-created_at"] def __str__(self) -> str: return self.code def is_available(self) -> bool: if not self.is_active: return False if self.expires_at is not None and timezone.now() >= self.expires_at: return False return True @property def public_short_url(self) -> str: from django.conf import settings origin = (getattr(settings, "PUBLIC_SHORT_URL", "") or "").rstrip("/") return f"{origin}/{self.code}" class Click(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) link = models.ForeignKey(ShortLink, on_delete=models.CASCADE, related_name="clicks") occurred_at = models.DateTimeField(auto_now_add=True) ip_hash = models.CharField(max_length=64, blank=True) user_agent = models.CharField(max_length=512, blank=True) referrer = models.CharField(max_length=1024, blank=True) class Meta: ordering = ["-occurred_at"] def __str__(self) -> str: return f"{self.link.code} @ {self.occurred_at}"