@ -321,76 +321,122 @@ class Command(BaseCommand):
def create_narrator_layers ( self ) :
""" Create narrator layers - fixes empty slugs first """
from django.utils.text import slugify
from django.db.models import Q
# Fix ALL existing layers with empty, null, or invalid slugs
existing_layers = NarratorLayer . objects . filter ( Q ( slug__isnull = True ) | Q ( slug = ' ' ) | Q ( slug = ' ' ) )
self . stdout . write ( f " Found {existing_layers.count()} layers with empty slugs to fix " )
# Fix existing layers with empty or invalid slugs
existing_layers = NarratorLayer . objects . all ( )
for layer in existing_layers :
if not layer . slug or not layer . slug . strip ( ) :
# Generate proper slug
try :
if layer . name and isinstance ( layer . name , list ) and len ( layer . name ) > 0 :
text = layer . name [ 0 ] . get ( ' text ' , ' ' ) . strip ( )
if text :
new_slug = slugify ( text )
else :
new_slug = f " layer-{layer.number} "
# Generate proper slug
try :
if layer . name and isinstance ( layer . name , list ) and len ( layer . name ) > 0 :
text = layer . name [ 0 ] . get ( ' text ' , ' ' ) . strip ( )
if text :
new_slug = slugify ( text )
else :
new_slug = f " layer-{layer.number} "
except ( IndexError , KeyError , AttributeError , TypeError ) :
else :
new_slug = f " layer-{layer.number} "
# Ensure uniqueness
counter = 1
original_slug = new_slug
while NarratorLayer . objects . filter ( slug = new_slug ) . exclude ( pk = layer . pk ) . exists ( ) :
new_slug = f " {original_slug}-{counter} "
counter + = 1
layer . slug = new_slug
layer . save ( update_fields = [ ' slug ' ] )
self . stdout . write ( f " Fixed slug for layer {layer.number}: {new_slug} " )
except ( IndexError , KeyError , AttributeError , TypeError ) :
new_slug = f " layer-{layer.number} "
# Ensure uniqueness
counter = 1
original_slug = new_slug
while NarratorLayer . objects . filter ( slug = new_slug ) . exclude ( pk = layer . pk ) . exists ( ) :
new_slug = f " {original_slug}-{counter} "
counter + = 1
layer . slug = new_slug
layer . save ( update_fields = [ ' slug ' ] )
self . stdout . write ( f " Fixed slug for layer {layer.pk} (number={layer.number}): ' {new_slug} ' " )
# Now create or get narrator layers
# Now create or get narrator layers - use filter().first() to avoid duplicates
for layer_data in RUSSIAN_NARRATOR_LAYERS :
try :
layer , created = NarratorLayer . objects . get_or_create (
number = layer_data [ ' number ' ] ,
defaults = {
' name ' : [ { ' language_code ' : ' ru ' , ' text ' : layer_data [ ' name ' ] } ] ,
' description ' : [ { ' language_code ' : ' ru ' , ' text ' : layer_data [ ' description ' ] } ]
}
)
# Try to find existing layer by number
layer = NarratorLayer . objects . filter ( number = layer_data [ ' number ' ] ) . first ( )
if layer :
# Layer already exists
created = False
self . stdout . write ( f " Using existing layer {layer_data[ ' number ' ]} " )
else :
# Create new layer
layer = NarratorLayer . objects . create (
number = layer_data [ ' number ' ] ,
name = [ { ' language_code ' : ' ru ' , ' text ' : layer_data [ ' name ' ] } ] ,
description = [ { ' language_code ' : ' ru ' , ' text ' : layer_data [ ' description ' ] } ]
)
created = True
self . stdout . write ( f " Created new layer {layer_data[ ' number ' ]} " )
self . narrator_layers . append ( layer )
except Exception as e :
# If creation fails, try to get existing layer by number
self . stdout . write ( self . style . WARNING (
f " Warning creating layer {layer_data[ ' number ' ]}: {str(e)} "
self . stdout . write ( self . style . ERROR (
f " Error with layer {layer_data[ ' number ' ]}: {str(e)} "
) )
# Try one more time to get by number
try :
layer = NarratorLayer . objects . get ( number = layer_data [ ' number ' ] )
self . narrator_layers . append ( layer )
except NarratorLayer . DoesNotExist :
self . stdout . write ( self . style . ERROR (
f " Could not create or find layer {layer_data[ ' number ' ]} "
) )
layer = NarratorLayer . objects . filter ( number = layer_data [ ' number ' ] ) . first ( )
if layer :
self . narrator_layers . append ( layer )
except Exception as e2 :
self . stdout . write ( self . style . ERROR ( f " Final attempt failed: {str(e2)} " ) )
self . created_counts [ ' narrator_layers ' ] = len ( self . narrator_layers )
def create_reliability_statuses ( self ) :
""" Create transmitter reliability statuses - fixes duplicates first """
from django.utils.text import slugify
from django.db.models import Count
from django.db.models import Count , Q
# Fix records with empty/null slugs first
empty_slug_records = TransmitterReliability . objects . filter ( Q ( slug__isnull = True ) | Q ( slug = ' ' ) | Q ( slug = ' ' ) )
self . stdout . write ( f " Found {empty_slug_records.count()} reliability records with empty slugs " )
for record in empty_slug_records :
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 ' )} "
else :
from datetime import datetime
new_slug = f " reliability-{datetime.now().strftime( ' % Y % m %d % H % M % S %f ' )} "
except :
from datetime import datetime
new_slug = f " reliability-{datetime.now().strftime( ' % Y % m %d % H % M % S %f ' )} "
# 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 empty reliability slug: ' {new_slug} ' " )
# Find and fix duplicate slugs
duplicates = TransmitterReliability . objects . values ( ' slug ' ) . annotate (
count = Count ( ' id ' )
) . filter ( count__gt = 1 )
self . stdout . write ( f " Found {duplicates.count()} duplicate reliability slugs " )
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
records = list ( TransmitterReliability . objects . filter ( slug = slug_value ) )
self . stdout . write ( f " Processing {len(records)} records with slug ' {slug_value} ' " )
# Keep the first one, update others
for i , record in enumerate ( records ) :
if i == 0 :
continue # Keep first record as is
@ -420,15 +466,16 @@ class Command(BaseCommand):
record . slug = new_slug
record . save ( update_fields = [ ' slug ' ] )
self . stdout . write ( f " Fixed duplicate reliability slug: {new_slug} " )
self . stdout . write ( f " Fixed duplicate reliability slug: ' {new_slug}' " )
# Now create or get reliability statuses
# Now create or get reliability statuses - using filter().first() to avoid MultipleObjectsReturned
for reliability_data in RUSSIAN_RELIABILITY_LEVELS :
try :
# Try to get by slug first
reliability = TransmitterReliability . objects . filter ( slug = reliability_data [ ' slug ' ] ) . first ( )
if reliability :
created = False
self . stdout . write ( f " Using existing reliability: {reliability_data[ ' slug ' ]} " )
else :
# Create new one
reliability = TransmitterReliability . objects . create (
@ -437,11 +484,12 @@ class Command(BaseCommand):
color = reliability_data [ ' color ' ]
)
created = True
self . stdout . write ( f " Created new reliability: {reliability_data[ ' slug ' ]} " )
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 . stdout . write ( self . style . ERROR (
f " Error with reliability status {reliability_data[' slug ' ]}: {str(e)} "
) )
self . created_counts [ ' reliability_statuses ' ] = len ( self . reliability_statuses )
@ -449,18 +497,53 @@ class Command(BaseCommand):
def create_opinion_statuses ( self ) :
""" Create opinion statuses - fixes duplicates first """
from django.utils.text import slugify
from django.db.models import Count
from django.db.models import Count , Q
# Fix records with empty/null slugs first
empty_slug_records = OpinionStatus . objects . filter ( Q ( slug__isnull = True ) | Q ( slug = ' ' ) | Q ( slug = ' ' ) )
self . stdout . write ( f " Found {empty_slug_records.count()} opinion status records with empty slugs " )
for record in empty_slug_records :
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 ' )} "
else :
from datetime import datetime
new_slug = f " opinion-{datetime.now().strftime( ' % Y % m %d % H % M % S %f ' )} "
except :
from datetime import datetime
new_slug = f " opinion-{datetime.now().strftime( ' % Y % m %d % H % M % S %f ' )} "
# 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 empty opinion status slug: ' {new_slug} ' " )
# Find and fix duplicate slugs
duplicates = OpinionStatus . objects . values ( ' slug ' ) . annotate (
count = Count ( ' id ' )
) . filter ( count__gt = 1 )
self . stdout . write ( f " Found {duplicates.count()} duplicate opinion status slugs " )
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
records = list ( OpinionStatus . objects . filter ( slug = slug_value ) )
self . stdout . write ( f " Processing {len(records)} records with slug ' {slug_value} ' " )
# Keep the first one, update others
for i , record in enumerate ( records ) :
if i == 0 :
continue # Keep first record as is
@ -490,15 +573,16 @@ class Command(BaseCommand):
record . slug = new_slug
record . save ( update_fields = [ ' slug ' ] )
self . stdout . write ( f " Fixed duplicate opinion status slug: {new_slug} " )
self . stdout . write ( f " Fixed duplicate opinion status slug: ' {new_slug}' " )
# Now create or get opinion statuses
# Now create or get opinion statuses - using filter().first() to avoid MultipleObjectsReturned
for opinion_data in RUSSIAN_OPINION_STATUSES :
try :
# Try to get by slug first
opinion_status = OpinionStatus . objects . filter ( slug = opinion_data [ ' slug ' ] ) . first ( )
if opinion_status :
created = False
self . stdout . write ( f " Using existing opinion status: {opinion_data[ ' slug ' ]} " )
else :
# Create new one
opinion_status = OpinionStatus . objects . create (
@ -507,11 +591,12 @@ class Command(BaseCommand):
color = opinion_data [ ' color ' ]
)
created = True
self . stdout . write ( f " Created new opinion status: {opinion_data[ ' slug ' ]} " )
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 . stdout . write ( self . style . ERROR (
f " Error with opinion status {opinion_data[' slug ' ]}: {str(e)} "
) )
self . created_counts [ ' opinion_statuses ' ] = len ( self . opinion_statuses )
@ -578,24 +663,72 @@ class Command(BaseCommand):
def create_books_and_authors ( self ) :
""" Create books and authors """
# Create authors
from django.utils.text import slugify
# Create authors - check for existing ones first
for author_name in RUSSIAN_AUTHOR_NAMES [ : 15 ] :
author = BookAuthor . objects . create (
name = [ { ' language_code ' : ' ru ' , ' text ' : author_name } ] ,
slug = None # Will be auto-generated
)
self . authors . append ( author )
try :
# Check if author with this name already exists
existing_author = None
all_authors = BookAuthor . objects . all ( )
for auth in all_authors :
if auth . name and isinstance ( auth . name , list ) and len ( auth . name ) > 0 :
if auth . name [ 0 ] . get ( ' text ' , ' ' ) == author_name :
existing_author = auth
break
if existing_author :
author = existing_author
self . stdout . write ( f " Using existing author: {author_name} " )
else :
author = BookAuthor . objects . create (
name = [ { ' language_code ' : ' ru ' , ' text ' : author_name } ]
)
self . stdout . write ( f " Created new author: {author_name} " )
self . authors . append ( author )
except Exception as e :
self . stdout . write ( self . style . ERROR (
f " Error creating author {author_name}: {str(e)} "
) )
# Create books
# Create books - check for existing ones first
for book_title in RUSSIAN_BOOK_TITLES [ : 20 ] :
book = BookReference . objects . create (
title = [ { ' language_code ' : ' ru ' , ' text ' : book_title } ] ,
description = f " Классическое исламское произведение - {book_title} " ,
slug = None # Will be auto-generated
)
# Add random authors
book . authors . add ( * random . sample ( self . authors , random . randint ( 1 , 2 ) ) )
self . books . append ( book )
try :
# Generate slug to check for existing book
expected_slug = slugify ( book_title , allow_unicode = True )
# Try to find existing book by slug or title
book = BookReference . objects . filter ( slug = expected_slug ) . first ( )
if not book :
# Check by title as fallback
all_books = BookReference . objects . all ( )
for bk in all_books :
if bk . title and isinstance ( bk . title , list ) and len ( bk . title ) > 0 :
if bk . title [ 0 ] . get ( ' text ' , ' ' ) == book_title :
book = bk
break
if book :
self . stdout . write ( f " Using existing book: {book_title} " )
else :
book = BookReference . objects . create (
title = [ { ' language_code ' : ' ru ' , ' text ' : book_title } ] ,
description = [ { ' language_code ' : ' ru ' , ' text ' : f " Классическое исламское произведение - {book_title} " } ]
)
self . stdout . write ( f " Created new book: {book_title} " )
# Add random authors if we have any
if self . authors and book . authors . count ( ) == 0 :
num_authors = min ( random . randint ( 1 , 2 ) , len ( self . authors ) )
book . authors . add ( * random . sample ( self . authors , num_authors ) )
self . books . append ( book )
except Exception as e :
self . stdout . write ( self . style . ERROR (
f " Error creating book {book_title}: {str(e)} "
) )
self . created_counts [ ' authors ' ] = len ( self . authors )
self . created_counts [ ' books ' ] = len ( self . books )