Browse Source

Refactor slug generation logic across multiple models for improved robustness

- Enhanced the save methods in Hadis, HadisCategory, BookReference, Transmitter, and related models to ensure unique slug generation.
- Implemented robust error handling and fallback mechanisms for slug creation based on title fields, with timestamp-based fallbacks for empty or invalid titles.
- Removed unnecessary thumbnail handling from TransmittersAdmin and simplified the display_header method.
- Improved overall data integrity and consistency in slug management across the application.
master
Mohsen Taba 4 months ago
parent
commit
5e685332bb
  1. 19
      apps/hadis/admin/transmitter.py
  2. 62
      apps/hadis/models/category.py
  3. 203
      apps/hadis/models/hadis.py
  4. 63
      apps/hadis/models/reference.py
  5. 256
      apps/hadis/models/transmitter.py

19
apps/hadis/admin/transmitter.py

@ -134,7 +134,7 @@ class TransmittersAdmin(ModelAdmin):
fieldsets = (
(None, {
'fields': ('full_name', 'birth_year_hijri', 'death_year_hijri','known_as','nickname','thumbnail')
'fields': ('full_name', 'birth_year_hijri', 'death_year_hijri','known_as','nickname')
}),
(_('Additional Information'), {
'fields': ('description','origin','lived_in','died_in','kunya'),
@ -159,23 +159,8 @@ class TransmittersAdmin(ModelAdmin):
@display(description=_("Transmitter"), header=True)
def display_header(self, obj):
from django.templatetags.static import static
# Get thumbnail image path - use article's thumbnail if available, otherwise use default
thumbnail_path = obj.thumbnail.url if obj.thumbnail else None
return [
self.get_full_name_display(obj),
None,
None,
{
"path": thumbnail_path,
"height": 30,
"width": 50,
"borderless": True,
# "squared": True,
},
]
return self.get_full_name_display(obj),
class HadisTransmitterAdmin(ModelAdmin):

62
apps/hadis/models/category.py

@ -92,13 +92,61 @@ class HadisCategory(MPTTModel):
def save(self, *args, **kwargs):
self.full_clean()
if not self.slug:
title = self.title[0]['text']
base_slug = slugify(title, allow_unicode=True)
slug = base_slug
while HadisCategory.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}"
self.slug = slug
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):
title_text = first_item.get('text', '').strip()
if title_text:
base_slug = slugify(title_text, allow_unicode=True)
slug = base_slug
counter = 1
while HadisCategory.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"category-{suffix}"
counter = 1
while HadisCategory.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"category-{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"category-{suffix}"
counter = 1
while HadisCategory.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"category-{suffix}-{counter}"
counter += 1
self.slug = base_slug
else:
# Fallback if title is empty or invalid
import time
suffix = int(time.time() * 1000) % 1000000
base_slug = f"category-{suffix}"
counter = 1
while HadisCategory.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"category-{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"category-{suffix}"
counter = 1
while HadisCategory.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"category-{suffix}-{counter}"
counter += 1
self.slug = base_slug
super().save(*args, **kwargs)

203
apps/hadis/models/hadis.py

@ -19,14 +19,61 @@ class HadisCollection(models.Model):
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('updated at'))
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(self.title[0]['text'], allow_unicode=True)
slug = base_slug
counter = 1
while HadisCollection.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
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):
title_text = first_item.get('text', '').strip()
if title_text:
base_slug = slugify(title_text, allow_unicode=True)
slug = base_slug
counter = 1
while HadisCollection.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"collection-{suffix}"
counter = 1
while HadisCollection.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"collection-{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"collection-{suffix}"
counter = 1
while HadisCollection.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"collection-{suffix}-{counter}"
counter += 1
self.slug = base_slug
else:
# Fallback if title is empty or invalid
import time
suffix = int(time.time() * 1000) % 1000000
base_slug = f"collection-{suffix}"
counter = 1
while HadisCollection.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"collection-{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"collection-{suffix}"
counter = 1
while HadisCollection.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"collection-{suffix}-{counter}"
counter += 1
self.slug = base_slug
super().save(*args, **kwargs)
def __str__(self):
@ -132,9 +179,62 @@ class HadisStatus(models.Model):
description = models.JSONField(default = list , verbose_name=_('Description'))
def save(self, *args, **kwargs):
if not self.slug:
slug = slugify(self.title[0]['text'])
self.slug = slug
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):
title_text = first_item.get('text', '').strip()
if title_text:
slug = slugify(title_text)
# Ensure uniqueness
counter = 1
base_slug = slug
while HadisStatus.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"status-{suffix}"
counter = 1
while HadisStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"status-{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"status-{suffix}"
counter = 1
while HadisStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"status-{suffix}-{counter}"
counter += 1
self.slug = base_slug
else:
# Fallback if title is empty or invalid
import time
suffix = int(time.time() * 1000) % 1000000
base_slug = f"status-{suffix}"
counter = 1
while HadisStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"status-{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"status-{suffix}"
counter = 1
while HadisStatus.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"status-{suffix}-{counter}"
counter += 1
self.slug = base_slug
super().save(*args, **kwargs)
def __str__(self):
@ -195,51 +295,45 @@ class Hadis(models.Model):
return f"{self.number} - {self.title[0]['text']}" if self.title else f"Hadis {self.number}"
def save(self, *args, **kwargs):
"""
Override save to automatically generate smart slugs.
- If slug is empty, generates a new one
- Uses the first 8 words from the title (configurable)
- Ensures uniqueness with counters (-1, -2, etc.)
- Max length: 100 characters (configurable)
Examples:
>>> hadis = Hadis.objects.create(
... number=1877,
... title=[
... {
... "text": "Fatwa on Combining Prayers While Traveling and Missing Prayer",
... "language_code": "en"
... }
... ]
... )
>>> print(hadis.slug)
'fatwa-on-combining-prayers-while'
"""
# Generate slug if not already set
if not self.slug and self.title:
# Extract title text
# Generate slug if not already set or if slug is empty
if not self.slug or (isinstance(self.slug, str) and self.slug.strip() == ''):
title_text = None
if isinstance(self.title, list) and self.title:
# 1. Try to extract text if title exists
if self.title and isinstance(self.title, list) and len(self.title) > 0:
first_item = self.title[0]
if isinstance(first_item, dict):
title_text = first_item.get("text")
# Generate smart slug
# 2. If we found text, use smart slug
if title_text:
self.slug = generate_smart_slug(
text=title_text,
model_class=Hadis,
max_length=100, # ← Adjust max length here
keep_words=8, # ← Limit to 8 words (your requirement)
max_length=100,
keep_words=8,
instance=self,
)
# 3. CRITICAL FALLBACK: If no title text, use the number with unique suffix
else:
# Fallback if title is empty
self.slug = f"hadis-{self.number or 'unknown'}"
# We use a random suffix or timestamp to ensure uniqueness if multiple untitled hadiths exist
from datetime import datetime
import random
import time
# Use timestamp + random to ensure uniqueness
suffix = int(time.time() * 1000) % 1000000 # Use milliseconds for better uniqueness
base_slug = f"hadis-{self.number or 'unknown'}-{suffix}"
# Ensure uniqueness by checking database
counter = 1
while Hadis.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"hadis-{self.number or 'unknown'}-{suffix}-{counter}"
counter += 1
self.slug = base_slug
# Generate share_link before saving
if not self.share_link and self.slug:
self.share_link = f"{settings.SITE_DOMAIN}/hadis/{self.slug}"
# Call parent save
super().save(*args, **kwargs)
def _get_json_field(self, field_name: str, lang: Optional[str]=None , fallback: str = "en"):
@ -295,12 +389,6 @@ class Hadis(models.Model):
"""Get address details (returns full list, not localized)"""
return self.address_details if self.address_details else []
def save(self, *args, **kwargs):
# ساخت share_link قبل از ذخیره
if not self.share_link:
self.share_link = f"{settings.SITE_DOMAIN}/hadis/{self.slug}"
super().save(*args, **kwargs)
class Meta:
indexes = [
# Optimizes: Hadis.objects.filter(status=True).order_by('id')
@ -432,12 +520,21 @@ class HadisCorrection(models.Model):
instance=self,
)
else:
# Fallback if title is empty
self.slug = f"correction-{self.hadis.slug}-{self.id}"
# Fallback if title is empty - use timestamp for uniqueness
import time
suffix = int(time.time() * 1000) % 1000000
base_slug = f"correction-{self.hadis.slug if self.hadis and self.hadis.slug else 'unknown'}-{suffix}"
# Ensure uniqueness
counter = 1
while HadisCorrection.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"correction-{self.hadis.slug if self.hadis and self.hadis.slug else 'unknown'}-{suffix}-{counter}"
counter += 1
self.slug = base_slug
# Call parent save
if not self.share_link:
# Generate share_link before saving
if not self.share_link and self.slug and self.hadis and self.hadis.slug:
self.share_link = f"{settings.SITE_DOMAIN}/hadis/{self.hadis.slug}/corrections/{self.slug}"
super().save(*args, **kwargs)
def get_title(self,lang):

63
apps/hadis/models/reference.py

@ -136,14 +136,61 @@ class BookReference(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(self.title[0]['text'], allow_unicode=True)
slug = base_slug
counter = 1
while BookReference.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
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):
title_text = first_item.get('text', '').strip()
if title_text:
base_slug = slugify(title_text, allow_unicode=True)
slug = base_slug
counter = 1
while BookReference.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"book-{suffix}"
counter = 1
while BookReference.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"book-{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"book-{suffix}"
counter = 1
while BookReference.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"book-{suffix}-{counter}"
counter += 1
self.slug = base_slug
else:
# Fallback if title is empty or invalid
import time
suffix = int(time.time() * 1000) % 1000000
base_slug = f"book-{suffix}"
counter = 1
while BookReference.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"book-{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"book-{suffix}"
counter = 1
while BookReference.objects.filter(slug=base_slug).exclude(pk=self.pk).exists():
base_slug = f"book-{suffix}-{counter}"
counter += 1
self.slug = base_slug
super().save(*args, **kwargs)
class BookReferenceImage(models.Model):

256
apps/hadis/models/transmitter.py

@ -66,24 +66,58 @@ class NarratorLayer(models.Model):
return None
def save(self, *args, **kwargs):
if not self.slug:
if not self.slug or (isinstance(self.slug, str) and self.slug.strip() == ''):
# Try to get text from name field with robust error handling
try:
if self.name and isinstance(self.name, list) and len(self.name) > 0:
text = self.name[0].get('text', '').strip()
if text:
slug = slugify(text)
first_item = self.name[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 NarratorLayer.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
else:
# Fallback to layer number if text is empty
base_slug = f"layer-{self.number}"
slug = base_slug
counter = 1
while NarratorLayer.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
else:
# Fallback to layer number if text is empty
slug = f"layer-{self.number}"
# Fallback to layer number if name structure is invalid
base_slug = f"layer-{self.number}"
slug = base_slug
counter = 1
while NarratorLayer.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
else:
# Fallback to layer number if name structure is invalid
slug = f"layer-{self.number}"
base_slug = f"layer-{self.number}"
slug = base_slug
counter = 1
while NarratorLayer.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
except (IndexError, KeyError, AttributeError, TypeError):
# Fallback to layer number on any error
slug = f"layer-{self.number}"
self.slug = slug
base_slug = f"layer-{self.number}"
slug = base_slug
counter = 1
while NarratorLayer.objects.filter(slug=slug).exclude(pk=self.pk).exists():
slug = f"{base_slug}-{counter}"
counter += 1
self.slug = slug
super().save(*args, **kwargs)
class TransmitterReliability(models.Model):
@ -102,25 +136,59 @@ class TransmitterReliability(models.Model):
color = models.CharField(max_length=20, choices=ColorChoices.choices, verbose_name=_('color'))
def save(self, *args, **kwargs):
if not self.slug:
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:
text = self.title[0].get('text', '').strip()
if text:
slug = slugify(text)
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:
# Fallback to a timestamp-based slug
from datetime import datetime
slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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:
from datetime import datetime
slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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):
from datetime import datetime
slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
self.slug = 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
super().save(*args, **kwargs)
def __str__(self):
@ -229,15 +297,61 @@ class Transmitters(models.Model):
ordering = ('full_name',)
def save(self, *args, **kwargs):
if not self.slug:
name = self.full_name[0]
base_slug = slugify(name.get('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
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"):
@ -367,25 +481,59 @@ class OpinionStatus(models.Model):
color = models.CharField(max_length=20, choices=ColorChoices.choices, verbose_name=_('color'))
def save(self, *args, **kwargs):
if not self.slug:
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:
text = self.title[0].get('text', '').strip()
if text:
slug = slugify(text)
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:
# Fallback to a timestamp-based slug
from datetime import datetime
slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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:
from datetime import datetime
slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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):
from datetime import datetime
slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
self.slug = 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
super().save(*args, **kwargs)
def __str__(self):
@ -536,12 +684,22 @@ class TransmitterOriginalText(models.Model):
instance=self,
)
else:
# Fallback if title is empty
self.slug = f"original-text-{self.transmitter.slug}-{self.id or 'unknown'}"
# 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
# Call parent save
if not self.share_link:
# Generate share_link before saving
if not self.share_link and self.slug and self.transmitter and self.transmitter.slug:
self.share_link = f"{settings.SITE_DOMAIN}/hadis/narrators/{self.transmitter.slug}/original-texts/{self.slug}"
super().save(*args, **kwargs)

Loading…
Cancel
Save