|
|
|
@ -7,11 +7,12 @@ from django.utils.text import slugify |
|
|
|
from typing import Optional |
|
|
|
from utils.slug import generate_smart_slug |
|
|
|
from django.conf import settings |
|
|
|
from utils.mixins import ColorPaletteMixin |
|
|
|
from utils.mixins import ColorPaletteMixin, LowercaseSlugMixin |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NarratorLayer(models.Model): |
|
|
|
class NarratorLayer(LowercaseSlugMixin, models.Model): |
|
|
|
slug_source_field = 'name' |
|
|
|
""" |
|
|
|
Model for narrator layers/classes (Tabaqat) |
|
|
|
Represents the classification level of narrators in hadis chains |
|
|
|
@ -122,67 +123,14 @@ class NarratorLayer(models.Model): |
|
|
|
self.slug = slug |
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
|
|
|
class TransmitterReliability(ColorPaletteMixin, models.Model): |
|
|
|
class TransmitterReliability(ColorPaletteMixin, LowercaseSlugMixin, models.Model): |
|
|
|
slug_source_field = 'title' |
|
|
|
|
|
|
|
title = models.JSONField(default = list , verbose_name=_('Title')) |
|
|
|
slug = models.SlugField(max_length=255, verbose_name=_('slug'), blank=True,null=True) |
|
|
|
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs): |
|
|
|
if not self.slug or (isinstance(self.slug, str) and self.slug.strip() == ''): |
|
|
|
# Try to get text from title field with robust error handling |
|
|
|
try: |
|
|
|
if self.title and isinstance(self.title, list) and len(self.title) > 0: |
|
|
|
first_item = self.title[0] |
|
|
|
if isinstance(first_item, dict): |
|
|
|
text = first_item.get('text', '').strip() |
|
|
|
if text: |
|
|
|
slug = slugify(text) |
|
|
|
# Ensure uniqueness |
|
|
|
counter = 1 |
|
|
|
base_slug = slug |
|
|
|
while TransmitterReliability.objects.filter(slug=slug).exclude(pk=self.pk).exists(): |
|
|
|
slug = f"{base_slug}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = slug |
|
|
|
else: |
|
|
|
# Fallback to a timestamp-based slug |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"reliability-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while TransmitterReliability.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"reliability-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"reliability-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while TransmitterReliability.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"reliability-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"reliability-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while TransmitterReliability.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"reliability-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
except (IndexError, KeyError, AttributeError, TypeError): |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"reliability-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while TransmitterReliability.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"reliability-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
return self.title[0]['text'] if self.title else str(self.id) |
|
|
|
@ -210,7 +158,8 @@ class TransmitterReliability(ColorPaletteMixin, models.Model): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Transmitters(models.Model): |
|
|
|
class Transmitters(LowercaseSlugMixin, models.Model): |
|
|
|
slug_source_field = 'full_name' |
|
|
|
# class ReliabilityLevel(models.TextChoices): |
|
|
|
# VERY_RELIABLE = 'very_reliable', _('Very Reliable') |
|
|
|
# RELIABLE = 'reliable', _('Reliable') |
|
|
|
@ -313,63 +262,7 @@ class Transmitters(models.Model): |
|
|
|
return f"{settings.DOVODI_DOMAIN}/arguments/narrators/{self.slug}" |
|
|
|
return None |
|
|
|
|
|
|
|
def save(self, *args, **kwargs): |
|
|
|
if not self.slug or (isinstance(self.slug, str) and self.slug.strip() == ''): |
|
|
|
# Try to get text from full_name field with robust error handling |
|
|
|
try: |
|
|
|
if self.full_name and isinstance(self.full_name, list) and len(self.full_name) > 0: |
|
|
|
first_item = self.full_name[0] |
|
|
|
if isinstance(first_item, dict): |
|
|
|
name_text = first_item.get('text', '').strip() |
|
|
|
if name_text: |
|
|
|
base_slug = slugify(name_text, allow_unicode=True) |
|
|
|
slug = base_slug |
|
|
|
counter = 1 |
|
|
|
while Transmitters.objects.filter(slug=slug).exclude(pk=self.pk).exists(): |
|
|
|
slug = f"{base_slug}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = slug |
|
|
|
else: |
|
|
|
# Fallback if text is empty |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"transmitter-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while Transmitters.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"transmitter-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
# Fallback if structure is invalid |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"transmitter-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while Transmitters.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"transmitter-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
# Fallback if full_name is empty or invalid |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"transmitter-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while Transmitters.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"transmitter-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
except (IndexError, KeyError, AttributeError, TypeError): |
|
|
|
# Fallback on any error |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"transmitter-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while Transmitters.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"transmitter-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
|
|
def _get_json_field(self, field_name: str, lang: Optional[str]=None , fallback: str = "en"): |
|
|
|
""" |
|
|
|
@ -492,66 +385,13 @@ class HadisTransmitter(models.Model): |
|
|
|
return f'{self.hadis.number} - Chain {self.chain_index} - {self.transmitter} (Pos: {self.order})' |
|
|
|
|
|
|
|
|
|
|
|
class OpinionStatus(ColorPaletteMixin, models.Model): |
|
|
|
class OpinionStatus(ColorPaletteMixin, LowercaseSlugMixin, models.Model): |
|
|
|
slug_source_field = 'title' |
|
|
|
|
|
|
|
title = models.JSONField(default = list , verbose_name=_('Title')) |
|
|
|
slug = models.SlugField(max_length=255, verbose_name=_('slug'), blank=True,null=True) |
|
|
|
|
|
|
|
def save(self, *args, **kwargs): |
|
|
|
if not self.slug or (isinstance(self.slug, str) and self.slug.strip() == ''): |
|
|
|
# Try to get text from title field with robust error handling |
|
|
|
try: |
|
|
|
if self.title and isinstance(self.title, list) and len(self.title) > 0: |
|
|
|
first_item = self.title[0] |
|
|
|
if isinstance(first_item, dict): |
|
|
|
text = first_item.get('text', '').strip() |
|
|
|
if text: |
|
|
|
slug = slugify(text) |
|
|
|
# Ensure uniqueness |
|
|
|
counter = 1 |
|
|
|
base_slug = slug |
|
|
|
while OpinionStatus.objects.filter(slug=slug).exclude(pk=self.pk).exists(): |
|
|
|
slug = f"{base_slug}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = slug |
|
|
|
else: |
|
|
|
# Fallback to a timestamp-based slug |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"opinion-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while OpinionStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"opinion-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"opinion-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while OpinionStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"opinion-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
else: |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"opinion-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while OpinionStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"opinion-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
except (IndexError, KeyError, AttributeError, TypeError): |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
base_slug = f"opinion-{suffix}" |
|
|
|
counter = 1 |
|
|
|
while OpinionStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"opinion-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
return self.title[0]['text'] if self.title else str(self.id) |
|
|
|
@ -695,37 +535,8 @@ class TransmitterOriginalText(models.Model): |
|
|
|
""" |
|
|
|
Override save to automatically generate smart slugs. |
|
|
|
""" |
|
|
|
|
|
|
|
# Generate slug if not already set |
|
|
|
if not self.slug and self.title: |
|
|
|
# Extract title text |
|
|
|
title_text = None |
|
|
|
if isinstance(self.title, list) and self.title: |
|
|
|
first_item = self.title[0] |
|
|
|
if isinstance(first_item, dict): |
|
|
|
title_text = first_item.get("text") |
|
|
|
|
|
|
|
# Generate smart slug |
|
|
|
if title_text: |
|
|
|
self.slug = generate_smart_slug( |
|
|
|
text=title_text, |
|
|
|
model_class=TransmitterOriginalText, |
|
|
|
max_length=100, # ← Adjust max length here |
|
|
|
keep_words=8, # ← Limit to 8 words (your requirement) |
|
|
|
instance=self, |
|
|
|
) |
|
|
|
else: |
|
|
|
# Fallback if title is empty - use timestamp for uniqueness |
|
|
|
import time |
|
|
|
suffix = int(time.time() * 1000) % 1000000 |
|
|
|
transmitter_slug = self.transmitter.slug if self.transmitter and self.transmitter.slug else 'unknown' |
|
|
|
base_slug = f"original-text-{transmitter_slug}-{suffix}" |
|
|
|
# Ensure uniqueness |
|
|
|
counter = 1 |
|
|
|
while TransmitterOriginalText.objects.filter(slug=base_slug).exclude(pk=self.pk).exists(): |
|
|
|
base_slug = f"original-text-{transmitter_slug}-{suffix}-{counter}" |
|
|
|
counter += 1 |
|
|
|
self.slug = base_slug |
|
|
|
from utils.slug import build_slug_for_instance |
|
|
|
build_slug_for_instance(self, source_field='title') |
|
|
|
|
|
|
|
# Generate/update share_link before saving |
|
|
|
if self.slug and self.transmitter and self.transmitter.slug: |
|
|
|
|