Browse Source

feat(hadis): add uncertain multi-narrator support to transmitter chains

master
Mohsen Taba 3 weeks ago
parent
commit
4e3fe9b5b4
  1. 33
      apps/hadis/migrations/0038_alter_booksubjectarea_options_and_more.py
  2. 18
      apps/hadis/models/transmitter.py
  3. 5
      apps/hadis/serializers/hadis.py
  4. 30
      apps/hadis/serializers/serializers_admin.py
  5. 5
      apps/hadis/views/hadis.py
  6. 2
      apps/hadis/views_admin.py

33
apps/hadis/migrations/0038_alter_booksubjectarea_options_and_more.py

@ -0,0 +1,33 @@
# Generated by Django 4.2.30 on 2026-08-31 17:52
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('hadis', '0037_remove_bookedition_tags_remove_bookreference_tags_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='booksubjectarea',
options={'ordering': ('-created_at', '-id'), 'verbose_name': 'Subject Area', 'verbose_name_plural': 'Subject Areas'},
),
migrations.AddField(
model_name='hadistransmitter',
name='is_uncertain',
field=models.BooleanField(default=False, help_text='Whether this transmission node is doubtful between multiple candidate narrators', verbose_name='is uncertain/doubtful'),
),
migrations.AddField(
model_name='hadistransmitter',
name='uncertain_transmitters',
field=models.ManyToManyField(blank=True, help_text='Candidate narrators when is_uncertain is True', related_name='uncertain_hadis_nodes', to='hadis.transmitters', verbose_name='uncertain candidate transmitters'),
),
migrations.AlterField(
model_name='hadistransmitter',
name='transmitter',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hadises', to='hadis.transmitters', verbose_name='transmitter'),
),
]

18
apps/hadis/models/transmitter.py

@ -345,9 +345,23 @@ class HadisTransmitter(models.Model):
)
transmitter = models.ForeignKey(
Transmitters,
on_delete=models.CASCADE,
on_delete=models.SET_NULL,
verbose_name=_('transmitter'),
related_name='hadises'
related_name='hadises',
null=True,
blank=True
)
is_uncertain = models.BooleanField(
default=False,
verbose_name=_('is uncertain/doubtful'),
help_text=_('Whether this transmission node is doubtful between multiple candidate narrators')
)
uncertain_transmitters = models.ManyToManyField(
Transmitters,
blank=True,
related_name='uncertain_hadis_nodes',
verbose_name=_('uncertain candidate transmitters'),
help_text=_('Candidate narrators when is_uncertain is True')
)
chain_index = models.PositiveIntegerField(

5
apps/hadis/serializers/hadis.py

@ -789,15 +789,16 @@ class TransmitterSyncSerializer(serializers.ModelSerializer):
class HadisTransmitterSerializer(serializers.ModelSerializer):
"""Serializer for HadisTransmitter with transmitter details"""
transmitter = TransmitterShortSerializer(read_only=True)
uncertain_transmitters = TransmitterShortSerializer(many=True, read_only=True)
layer = serializers.SerializerMethodField()
status = serializers.SerializerMethodField()
class Meta:
model = HadisTransmitter
fields = [
'id', 'order', 'is_gap','layer', 'transmitter', 'status'
'id', 'order', 'is_gap', 'is_uncertain', 'layer', 'transmitter', 'uncertain_transmitters', 'status'
]

30
apps/hadis/serializers/serializers_admin.py

@ -1613,12 +1613,28 @@ class AdminCategoryQuranVerseSerializer(serializers.ModelSerializer):
class AdminHadisTransmitterSerializer(serializers.ModelSerializer):
transmitter_detail = AdminTransmitterListSerializer(source="transmitter", read_only=True)
uncertain_transmitters = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Transmitters.objects.all(),
required=False
)
uncertain_transmitters_detail = AdminTransmitterListSerializer(
source="uncertain_transmitters",
many=True,
read_only=True
)
class Meta:
model = HadisTransmitter
fields = [
"id",
"hadis",
"transmitter",
"transmitter_detail",
"is_uncertain",
"uncertain_transmitters",
"uncertain_transmitters_detail",
"chain_index",
"narrator_layer",
"status",
@ -1626,6 +1642,20 @@ class AdminHadisTransmitterSerializer(serializers.ModelSerializer):
"is_gap",
]
def create(self, validated_data):
uncertain_transmitters = validated_data.pop("uncertain_transmitters", None)
instance = super().create(validated_data)
if uncertain_transmitters is not None:
instance.uncertain_transmitters.set(uncertain_transmitters)
return instance
def update(self, instance, validated_data):
uncertain_transmitters = validated_data.pop("uncertain_transmitters", None)
instance = super().update(instance, validated_data)
if uncertain_transmitters is not None:
instance.uncertain_transmitters.set(uncertain_transmitters)
return instance
class AdminTransmitterOpinionSerializer(serializers.ModelSerializer):
scholar_name = serializers.JSONField(required=False, default=list)

5
apps/hadis/views/hadis.py

@ -575,8 +575,9 @@ class HadisTransmittersView(RetrieveAPIView):
# We start with the base optimization (select_related)
transmitter_qs = HadisTransmitter.objects.select_related(
'transmitter',
'narrator_layer'
).order_by('order')
'narrator_layer',
'status'
).prefetch_related('uncertain_transmitters').order_by('order')
# 3. Apply the filter to the Child Query (if param exists)
if layer_slug:

2
apps/hadis/views_admin.py

@ -673,7 +673,7 @@ class AdminHadisTransmitterViewSet(ModelViewSet):
parser_classes = (JSONParser, MultiPartParser, FormParser)
def get_queryset(self):
queryset = HadisTransmitter.objects.all().select_related("transmitter", "narrator_layer", "status")
queryset = HadisTransmitter.objects.all().select_related("transmitter", "narrator_layer", "status").prefetch_related("uncertain_transmitters")
hadis_id = self.request.query_params.get("hadis_id")
if hadis_id:
queryset = queryset.filter(hadis_id=hadis_id)

Loading…
Cancel
Save