Browse Source

Refactor slug generation and duplicate handling in reliability and opinion statuses

- Enhanced the slug generation process in the TransmitterReliability and OpinionStatus models to include robust error handling, ensuring unique slugs are created even when the title is invalid or empty.
- Implemented a mechanism to fix duplicate slugs during the seeding process, ensuring data integrity and preventing conflicts.
- Updated the seeding command to handle existing records more efficiently, improving overall reliability and opinion status creation.
master
mortezaei 4 months ago
parent
commit
ab3cc9f1bf
  1. 148
      apps/hadis/management/commands/seed_complete_hadis_data.py
  2. 53
      apps/hadis/models/transmitter.py

148
apps/hadis/management/commands/seed_complete_hadis_data.py

@ -377,30 +377,142 @@ class Command(BaseCommand):
self.created_counts['narrator_layers'] = len(self.narrator_layers)
def create_reliability_statuses(self):
"""Create transmitter reliability statuses"""
"""Create transmitter reliability statuses - fixes duplicates first"""
from django.utils.text import slugify
from django.db.models import Count
# Find and fix duplicate slugs
duplicates = TransmitterReliability.objects.values('slug').annotate(
count=Count('id')
).filter(count__gt=1)
for dup in duplicates:
slug_value = dup['slug']
# Get all records with this slug
records = TransmitterReliability.objects.filter(slug=slug_value)
# Keep the first one, update or delete others
for i, record in enumerate(records):
if i == 0:
continue # Keep first record as is
else:
# Update slug to make it unique
try:
if record.title and isinstance(record.title, list) and len(record.title) > 0:
text = record.title[0].get('text', '').strip()
if text:
new_slug = slugify(text)
else:
from datetime import datetime
new_slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
else:
from datetime import datetime
new_slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
except:
from datetime import datetime
new_slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
# Ensure uniqueness
counter = 1
original_slug = new_slug
while TransmitterReliability.objects.filter(slug=new_slug).exclude(pk=record.pk).exists():
new_slug = f"{original_slug}-{counter}"
counter += 1
record.slug = new_slug
record.save(update_fields=['slug'])
self.stdout.write(f"Fixed duplicate reliability slug: {new_slug}")
# Now create or get reliability statuses
for reliability_data in RUSSIAN_RELIABILITY_LEVELS:
reliability, created = TransmitterReliability.objects.get_or_create(
slug=reliability_data['slug'],
defaults={
'title': [{'language_code': 'ru', 'text': reliability_data['title']}],
'color': reliability_data['color']
}
)
self.reliability_statuses.append(reliability)
try:
# Try to get by slug first
reliability = TransmitterReliability.objects.filter(slug=reliability_data['slug']).first()
if reliability:
created = False
else:
# Create new one
reliability = TransmitterReliability.objects.create(
slug=reliability_data['slug'],
title=[{'language_code': 'ru', 'text': reliability_data['title']}],
color=reliability_data['color']
)
created = True
self.reliability_statuses.append(reliability)
except Exception as e:
self.stdout.write(self.style.WARNING(
f"Warning creating reliability status {reliability_data['slug']}: {str(e)}"
))
self.created_counts['reliability_statuses'] = len(self.reliability_statuses)
def create_opinion_statuses(self):
"""Create opinion statuses"""
"""Create opinion statuses - fixes duplicates first"""
from django.utils.text import slugify
from django.db.models import Count
# Find and fix duplicate slugs
duplicates = OpinionStatus.objects.values('slug').annotate(
count=Count('id')
).filter(count__gt=1)
for dup in duplicates:
slug_value = dup['slug']
# Get all records with this slug
records = OpinionStatus.objects.filter(slug=slug_value)
# Keep the first one, update or delete others
for i, record in enumerate(records):
if i == 0:
continue # Keep first record as is
else:
# Update slug to make it unique
try:
if record.title and isinstance(record.title, list) and len(record.title) > 0:
text = record.title[0].get('text', '').strip()
if text:
new_slug = slugify(text)
else:
from datetime import datetime
new_slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
else:
from datetime import datetime
new_slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
except:
from datetime import datetime
new_slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}-{i}"
# Ensure uniqueness
counter = 1
original_slug = new_slug
while OpinionStatus.objects.filter(slug=new_slug).exclude(pk=record.pk).exists():
new_slug = f"{original_slug}-{counter}"
counter += 1
record.slug = new_slug
record.save(update_fields=['slug'])
self.stdout.write(f"Fixed duplicate opinion status slug: {new_slug}")
# Now create or get opinion statuses
for opinion_data in RUSSIAN_OPINION_STATUSES:
opinion_status, created = OpinionStatus.objects.get_or_create(
slug=opinion_data['slug'],
defaults={
'title': [{'language_code': 'ru', 'text': opinion_data['title']}],
'color': opinion_data['color']
}
)
self.opinion_statuses.append(opinion_status)
try:
# Try to get by slug first
opinion_status = OpinionStatus.objects.filter(slug=opinion_data['slug']).first()
if opinion_status:
created = False
else:
# Create new one
opinion_status = OpinionStatus.objects.create(
slug=opinion_data['slug'],
title=[{'language_code': 'ru', 'text': opinion_data['title']}],
color=opinion_data['color']
)
created = True
self.opinion_statuses.append(opinion_status)
except Exception as e:
self.stdout.write(self.style.WARNING(
f"Warning creating opinion status {opinion_data['slug']}: {str(e)}"
))
self.created_counts['opinion_statuses'] = len(self.opinion_statuses)

53
apps/hadis/models/transmitter.py

@ -68,7 +68,22 @@ class NarratorLayer(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
slug = slugify(self.name[0]['text'])
# 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)
else:
# Fallback to layer number if text is empty
slug = f"layer-{self.number}"
else:
# Fallback to layer number if name structure is invalid
slug = f"layer-{self.number}"
except (IndexError, KeyError, AttributeError, TypeError):
# Fallback to layer number on any error
slug = f"layer-{self.number}"
self.slug = slug
super().save(*args, **kwargs)
@ -89,7 +104,23 @@ class TransmitterReliability(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
slug = slugify(self.title[0]['text'])
# 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)
else:
# Fallback to a timestamp-based slug
from datetime import datetime
slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
else:
from datetime import datetime
slug = f"reliability-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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
super().save(*args, **kwargs)
@ -344,7 +375,23 @@ class OpinionStatus(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
slug = slugify(self.title[0]['text'])
# 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)
else:
# Fallback to a timestamp-based slug
from datetime import datetime
slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
else:
from datetime import datetime
slug = f"opinion-{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
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
super().save(*args, **kwargs)

Loading…
Cancel
Save