Browse Source

Transmitters Reliability changed.

master
Mohsen Taba 5 months ago
parent
commit
27c72087d3
  1. 30
      apps/hadis/docs.py
  2. 91
      apps/hadis/management/commands/migrate_transmitter_reliability.py
  3. 47
      apps/hadis/migrations/0068_transmitterreliability.py
  4. 134
      apps/hadis/migrations/0069_alter_transmitters_reliability.py
  5. 24
      apps/hadis/migrations/0070_alter_transmitters_reliability.py
  6. 109
      apps/hadis/migrations/0070_migrate_transmitter_reliability_data.py
  7. 65
      apps/hadis/models/transmitter.py
  8. 32
      apps/hadis/serializers/hadis.py

30
apps/hadis/docs.py

@ -772,7 +772,11 @@ transmitter_list_swagger = swagger_auto_schema(
"death_year_hijri": 275,
"known_as": "Imam Abu Daud",
"nickname": "Al-Sijistani",
"reliability": "very_reliable",
"reliability": {
"id": 7,
"title": "Very Reliable",
"color": "green"
},
"madhhab": "sunni",
"generation": 3
},
@ -784,7 +788,11 @@ transmitter_list_swagger = swagger_auto_schema(
"death_year_hijri": 329,
"known_as": "Thiqat al-Islam",
"nickname": None,
"reliability": "very_reliable",
"reliability": {
"id": 7,
"title": "Very Reliable",
"color": "green"
},
"madhhab": "shia",
"generation": 4
}
@ -829,7 +837,11 @@ transmitter_detail_swagger = swagger_auto_schema(
"birth_year_hijri": 202,
"death_year_hijri": 275,
"age_at_death": 73,
"reliability": "very_reliable",
"reliability": {
"id": 7,
"title": "Very Reliable",
"color": "green"
},
"madhhab": "sunni",
"in_sahih_bukhari": False,
"in_sahih_muslim": True,
@ -878,7 +890,11 @@ transmitter_sync_swagger = swagger_auto_schema(
"death_year_hijri": 329,
"age_at_death": None,
"generation": None,
"reliability": "unknown",
"reliability": {
"id": 7,
"title": "Very Reliable",
"color": "green"
},
"madhhab": "unknown",
"in_sahih_muslim": False,
"in_sahih_bukhari": False,
@ -935,7 +951,11 @@ transmitter_sync_swagger = swagger_auto_schema(
"death_year_hijri": 275,
"age_at_death": 73,
"generation": 3,
"reliability": "very_reliable",
"reliability": {
"id": 7,
"title": "Very Reliable",
"color": "green"
},
"madhhab": "shafii",
"in_sahih_muslim": False,
"in_sahih_bukhari": False,

91
apps/hadis/management/commands/migrate_transmitter_reliability.py

@ -0,0 +1,91 @@
"""
Management command to migrate transmitter reliability data from CharField to ForeignKey.
Run this after the migration 0069_alter_transmitters_reliability has been applied.
"""
from django.core.management.base import BaseCommand
from apps.hadis.models import Transmitters, TransmitterReliability
class Command(BaseCommand):
help = 'Migrate transmitter reliability data from CharField to ForeignKey'
def handle(self, *args, **options):
self.stdout.write('Starting transmitter reliability data migration...')
# Get or create reliability objects
reliability_mapping = self.get_reliability_mapping()
# Update transmitters
updated_count = 0
for transmitter in Transmitters.objects.all():
old_value = getattr(transmitter, 'reliability_old', None)
if old_value and old_value in reliability_mapping:
transmitter.reliability = reliability_mapping[old_value]
transmitter.save()
updated_count += 1
elif not transmitter.reliability:
# Set default for transmitters without reliability
transmitter.reliability = reliability_mapping['unknown']
transmitter.save()
updated_count += 1
self.stdout.write(
self.style.SUCCESS(
f'Successfully migrated {updated_count} transmitters'
)
)
def get_reliability_mapping(self):
"""Get mapping of old values to new TransmitterReliability objects"""
mapping = {}
# Define the reliability levels
reliability_data = [
('very_reliable', 'Very Reliable', 'green'),
('reliable', 'Reliable', 'blue'),
('acceptable', 'Acceptable', 'yellow'),
('weak', 'Weak', 'orange'),
('very_weak', 'Very Weak', 'red'),
('unknown', 'Unknown', 'gray'),
]
for value, title, color in reliability_data:
obj, created = TransmitterReliability.objects.get_or_create(
title__0__text=title, # Check if object exists by title
defaults={
'title': [
{'text': title, 'language_code': 'en'},
{'text': self.get_persian_title(title), 'language_code': 'fa'},
{'text': self.get_russian_title(title), 'language_code': 'ru'}
],
'color': color
}
)
mapping[value] = obj
return mapping
def get_persian_title(self, english_title):
"""Get Persian translation"""
translations = {
'Very Reliable': 'بسیار قابل اعتماد',
'Reliable': 'قابل اعتماد',
'Acceptable': 'قابل قبول',
'Weak': 'ضعیف',
'Very Weak': 'بسیار ضعیف',
'Unknown': 'نامشخص'
}
return translations.get(english_title, english_title)
def get_russian_title(self, english_title):
"""Get Russian translation"""
translations = {
'Very Reliable': 'Очень надежный',
'Reliable': 'Надежный',
'Acceptable': 'Приемлемый',
'Weak': 'Слабый',
'Very Weak': 'Очень слабый',
'Unknown': 'Неизвестный'
}
return translations.get(english_title, english_title)

47
apps/hadis/migrations/0068_transmitterreliability.py

@ -0,0 +1,47 @@
# Generated by Django 4.2.27 on 2025-12-23 08:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("hadis", "0067_bookreference_hadis_bookr_id_1b53f6_idx_and_more"),
]
operations = [
migrations.CreateModel(
name="TransmitterReliability",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.JSONField(default=list, verbose_name="Title")),
(
"color",
models.CharField(
choices=[
("red", "Red"),
("green", "Green"),
("blue", "Blue"),
("yellow", "Yellow"),
("orange", "Orange"),
("purple", "Purple"),
("gray", "Gray"),
],
max_length=20,
verbose_name="color",
),
),
],
options={
"verbose_name": "transmitter reliability",
"verbose_name_plural": "transmitter reliability",
},
),
]

134
apps/hadis/migrations/0069_alter_transmitters_reliability.py

@ -0,0 +1,134 @@
# Generated by Django 4.2.27 on 2025-12-23 08:32
from django.db import migrations, models
import django.db.models.deletion
def create_reliability_objects(apps, schema_editor):
"""Create TransmitterReliability objects for each reliability level"""
TransmitterReliability = apps.get_model('hadis', 'TransmitterReliability')
# Define the reliability levels with their data
reliability_data = [
{
'title': [
{'text': 'Very Reliable', 'language_code': 'en'},
{'text': 'بسیار قابل اعتماد', 'language_code': 'fa'},
{'text': 'Очень надежный', 'language_code': 'ru'}
],
'color': 'green',
'value': 'very_reliable'
},
{
'title': [
{'text': 'Reliable', 'language_code': 'en'},
{'text': 'قابل اعتماد', 'language_code': 'fa'},
{'text': 'Надежный', 'language_code': 'ru'}
],
'color': 'blue',
'value': 'reliable'
},
{
'title': [
{'text': 'Acceptable', 'language_code': 'en'},
{'text': 'قابل قبول', 'language_code': 'fa'},
{'text': 'Приемлемый', 'language_code': 'ru'}
],
'color': 'yellow',
'value': 'acceptable'
},
{
'title': [
{'text': 'Weak', 'language_code': 'en'},
{'text': 'ضعیف', 'language_code': 'fa'},
{'text': 'Слабый', 'language_code': 'ru'}
],
'color': 'orange',
'value': 'weak'
},
{
'title': [
{'text': 'Very Weak', 'language_code': 'en'},
{'text': 'بسیار ضعیف', 'language_code': 'fa'},
{'text': 'Очень слабый', 'language_code': 'ru'}
],
'color': 'red',
'value': 'very_weak'
},
{
'title': [
{'text': 'Unknown', 'language_code': 'en'},
{'text': 'نامشخص', 'language_code': 'fa'},
{'text': 'Неизвестный', 'language_code': 'ru'}
],
'color': 'gray',
'value': 'unknown'
}
]
reliability_objects = {}
for data in reliability_data:
obj = TransmitterReliability.objects.create(
title=data['title'],
color=data['color']
)
reliability_objects[data['value']] = obj
return reliability_objects
def migrate_transmitter_data(apps, schema_editor):
"""Migrate existing transmitter reliability data"""
Transmitters = apps.get_model('hadis', 'Transmitters')
# Create reliability objects
reliability_objects = create_reliability_objects(apps, schema_editor)
# Update all transmitters to use the new temporary field
for transmitter in Transmitters.objects.all():
old_value = getattr(transmitter, 'reliability', None)
if old_value and old_value in reliability_objects:
transmitter.reliability_new = reliability_objects[old_value]
else:
# Default to unknown if no value or invalid value
transmitter.reliability_new = reliability_objects['unknown']
transmitter.save()
def reverse_migrate(apps, schema_editor):
"""Reverse migration - not needed since we're changing field types"""
pass
class Migration(migrations.Migration):
dependencies = [
("hadis", "0068_transmitterreliability"),
]
operations = [
# Step 1: Add a temporary ForeignKey field
migrations.AddField(
model_name='transmitters',
name='reliability_new',
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="transmitters_temp",
to="hadis.transmitterreliability",
verbose_name="reliability",
null=True,
),
),
# Step 2: Run data migration to populate the new field
migrations.RunPython(migrate_transmitter_data, reverse_migrate),
# Step 3: Remove the old field
migrations.RemoveField(
model_name='transmitters',
name='reliability',
),
# Step 4: Rename the new field to the final name
migrations.RenameField(
model_name='transmitters',
old_name='reliability_new',
new_name='reliability',
),
]

24
apps/hadis/migrations/0070_alter_transmitters_reliability.py

@ -0,0 +1,24 @@
# Generated by Django 4.2.27 on 2025-12-23 08:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("hadis", "0069_alter_transmitters_reliability"),
]
operations = [
migrations.AlterField(
model_name="transmitters",
name="reliability",
field=models.ForeignKey(
default=12,
on_delete=django.db.models.deletion.CASCADE,
related_name="transmitters",
to="hadis.transmitterreliability",
verbose_name="reliability",
),
),
]

109
apps/hadis/migrations/0070_migrate_transmitter_reliability_data.py

@ -0,0 +1,109 @@
# Migration to handle data conversion for transmitter reliability field
from django.db import migrations
def create_reliability_objects(apps, schema_editor):
"""Create TransmitterReliability objects for each reliability level"""
TransmitterReliability = apps.get_model('hadis', 'TransmitterReliability')
# Define the reliability levels with their data
reliability_data = [
{
'title': [
{'text': 'Very Reliable', 'language_code': 'en'},
{'text': 'بسیار قابل اعتماد', 'language_code': 'fa'},
{'text': 'Очень надежный', 'language_code': 'ru'}
],
'color': 'green',
'value': 'very_reliable'
},
{
'title': [
{'text': 'Reliable', 'language_code': 'en'},
{'text': 'قابل اعتماد', 'language_code': 'fa'},
{'text': 'Надежный', 'language_code': 'ru'}
],
'color': 'blue',
'value': 'reliable'
},
{
'title': [
{'text': 'Acceptable', 'language_code': 'en'},
{'text': 'قابل قبول', 'language_code': 'fa'},
{'text': 'Приемлемый', 'language_code': 'ru'}
],
'color': 'yellow',
'value': 'acceptable'
},
{
'title': [
{'text': 'Weak', 'language_code': 'en'},
{'text': 'ضعیف', 'language_code': 'fa'},
{'text': 'Слабый', 'language_code': 'ru'}
],
'color': 'orange',
'value': 'weak'
},
{
'title': [
{'text': 'Very Weak', 'language_code': 'en'},
{'text': 'بسیار ضعیف', 'language_code': 'fa'},
{'text': 'Очень слабый', 'language_code': 'ru'}
],
'color': 'red',
'value': 'very_weak'
},
{
'title': [
{'text': 'Unknown', 'language_code': 'en'},
{'text': 'نامشخص', 'language_code': 'fa'},
{'text': 'Неизвестный', 'language_code': 'ru'}
],
'color': 'gray',
'value': 'unknown'
}
]
reliability_objects = {}
for data in reliability_data:
obj = TransmitterReliability.objects.create(
title=data['title'],
color=data['color']
)
reliability_objects[data['value']] = obj
return reliability_objects
def migrate_transmitter_data(apps, schema_editor):
"""Migrate existing transmitter reliability data"""
Transmitters = apps.get_model('hadis', 'Transmitters')
# Create reliability objects
reliability_objects = create_reliability_objects(apps, schema_editor)
# Update all transmitters to use the new foreign key references
for transmitter in Transmitters.objects.all():
old_value = getattr(transmitter, 'reliability', None)
if old_value and old_value in reliability_objects:
transmitter.reliability = reliability_objects[old_value]
transmitter.save(update_fields=['reliability'])
elif old_value == 'unknown' or not old_value:
# Default to unknown if no value or unknown
transmitter.reliability = reliability_objects.get('unknown')
transmitter.save(update_fields=['reliability'])
def reverse_migrate(apps, schema_editor):
"""Reverse migration - not needed since we're changing field types"""
pass
class Migration(migrations.Migration):
dependencies = [
('hadis', '0069_alter_transmitters_reliability'),
]
operations = [
migrations.RunPython(migrate_transmitter_data, reverse_migrate),
]

65
apps/hadis/models/transmitter.py

@ -1,5 +1,6 @@
from tabnanny import verbose
from django.db import models
from django.utils.translation import gettext_lazy as _
from filer.fields.image import FilerImageField
@ -71,15 +72,54 @@ class NarratorLayer(models.Model):
self.slug = slug
super().save(*args, **kwargs)
class TransmitterReliability(models.Model):
class ColorChoices(models.TextChoices):
RED = 'red', _('Red')
GREEN = 'green', _('Green')
BLUE = 'blue', _('Blue')
YELLOW = 'yellow', _('Yellow')
ORANGE = 'orange', _('Orange')
PURPLE = 'purple', _('Purple')
GRAY = 'gray', _('Gray')
title = models.JSONField(default = list , verbose_name=_('Title'))
color = models.CharField(max_length=20, choices=ColorChoices.choices, verbose_name=_('color'))
def __str__(self):
return self.title[0]['text']
def get_title(self,lang):
"""
Get title for a specific language
"""
if not self.title or not isinstance(self.title, list):
return None
for tr in self.title:
if isinstance(tr, dict) and tr.get('language_code') == lang:
return tr.get('text', '')
for tr in self.title:
if isinstance(tr, dict) and tr.get('language_code') == 'en':
return tr.get('text', '')
return None
class Meta:
verbose_name = _('transmitter reliability')
verbose_name_plural = _('transmitter reliability')
class Transmitters(models.Model):
class ReliabilityLevel(models.TextChoices):
VERY_RELIABLE = 'very_reliable', _('Very Reliable')
RELIABLE = 'reliable', _('Reliable')
ACCEPTABLE = 'acceptable', _('Acceptable')
WEAK = 'weak', _('Weak')
VERY_WEAK = 'very_weak', _('Very Weak')
UNKNOWN = 'unknown', _('Unknown')
# class ReliabilityLevel(models.TextChoices):
# VERY_RELIABLE = 'very_reliable', _('Very Reliable')
# RELIABLE = 'reliable', _('Reliable')
# ACCEPTABLE = 'acceptable', _('Acceptable')
# WEAK = 'weak', _('Weak')
# VERY_WEAK = 'very_weak', _('Very Weak')
# UNKNOWN = 'unknown', _('Unknown')
class MadhhabChoices(models.TextChoices):
SHIA = 'shia', _('Shia')
@ -109,11 +149,12 @@ class Transmitters(models.Model):
age_at_death = models.PositiveIntegerField(verbose_name=_('Age at Death'), blank=True, null=True)
generation = models.PositiveIntegerField(verbose_name=_('Generation'), blank=True, null=True)
# Religious & Academic Information
reliability = models.CharField(
max_length=20,
choices=ReliabilityLevel.choices,
default=ReliabilityLevel.UNKNOWN,
verbose_name=_('Reliability Level')
reliability = models.ForeignKey(
TransmitterReliability,
on_delete=models.CASCADE,
verbose_name=_('reliability'),
related_name='transmitters',
default=12 # ID of 'Unknown' reliability
)
madhhab = models.CharField(
max_length=20,

32
apps/hadis/serializers/hadis.py

@ -258,6 +258,7 @@ class TransmitterSerializer(serializers.ModelSerializer):
full_name = LocalizedField()
known_as = LocalizedField()
nickname = LocalizedField()
reliability = serializers.SerializerMethodField()
class Meta:
model = Transmitters
@ -266,6 +267,16 @@ class TransmitterSerializer(serializers.ModelSerializer):
"known_as",'nickname','reliability','madhhab','generation'
]
def get_reliability(self, obj):
"""Serialize the reliability foreign key"""
if obj.reliability:
return {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, self.context.get('request')),
'color': obj.reliability.color
}
return None
class TransmitterShortSerializer(serializers.ModelSerializer):
"""Serializer for Transmitters"""
full_name = LocalizedField()
@ -308,6 +319,7 @@ class TransmitterDetailSerializer(serializers.ModelSerializer):
lived_in = LocalizedField()
died_in = LocalizedField()
description = LocalizedField()
reliability = serializers.SerializerMethodField()
class Meta:
model = Transmitters
@ -319,6 +331,16 @@ class TransmitterDetailSerializer(serializers.ModelSerializer):
"description",'generation'
]
def get_reliability(self, obj):
"""Serialize the reliability foreign key"""
if obj.reliability:
return {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, self.context.get('request')),
'color': obj.reliability.color
}
return None
class TransmitterSyncSerializer(serializers.ModelSerializer):
"""Serializer for syncing all transmitter data for offline mode"""
@ -337,6 +359,14 @@ class TransmitterSyncSerializer(serializers.ModelSerializer):
def get_biographical(self, obj):
"""Get biographical information (flattened)"""
request = self.context.get('request') # ← FIX: Define request
if obj.reliability:
r= {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, self.context.get('request')),
'color': obj.reliability.color
}
else :
r= None
return {
'full_name': get_localized_text(obj.full_name, request),
@ -350,7 +380,7 @@ class TransmitterSyncSerializer(serializers.ModelSerializer):
'death_year_hijri': obj.death_year_hijri,
'age_at_death': obj.age_at_death,
'generation': obj.generation,
'reliability': obj.reliability,
'reliability': r,
'madhhab': obj.madhhab,
'in_sahih_muslim': obj.in_sahih_muslim,
'in_sahih_bukhari': obj.in_sahih_bukhari,

Loading…
Cancel
Save